Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a9977e454 | ||
|
|
10701f4e64 | ||
|
|
8f4a0b1d91 | ||
|
|
65802e8741 | ||
|
|
4647d8a01a | ||
|
|
3bc0733e6e | ||
|
|
26d00745c8 | ||
|
|
065397496c | ||
|
|
5d30333587 | ||
|
|
a18d74c5b6 | ||
|
|
1e86feb8ae | ||
|
|
863babcecf | ||
|
|
a4c4b6b158 | ||
|
|
0e0b7e5103 | ||
|
|
0c033e2a9a | ||
|
|
41a4b119d1 | ||
|
|
b6d0b6e6be | ||
|
|
01edb2a7df | ||
|
|
ce8fd488aa | ||
|
|
2c1492169c | ||
|
|
50277142c7 | ||
|
|
d5015a0860 | ||
|
|
acd14969de | ||
|
|
16d018625f | ||
|
|
1d10b3afc4 | ||
|
|
04f4275236 | ||
|
|
a6026d6f6b |
@ -18,5 +18,5 @@ def load_about() -> dict[str, str]:
|
|||||||
with open(
|
with open(
|
||||||
os.path.join(HERE, "tutorcairn", "__about__.py"), "rt", encoding="utf-8"
|
os.path.join(HERE, "tutorcairn", "__about__.py"), "rt", encoding="utf-8"
|
||||||
) as f:
|
) as f:
|
||||||
exec(f.read(), about) # pylint: disable=exec-used
|
exec(f.read(), about)
|
||||||
return about
|
return about
|
||||||
|
|||||||
36
CHANGELOG.md
36
CHANGELOG.md
@ -19,6 +19,42 @@ instructions, because git commits are used to generate release notes:
|
|||||||
|
|
||||||
<!-- scriv-insert-here -->
|
<!-- scriv-insert-here -->
|
||||||
|
|
||||||
|
<a id='changelog-20.0.0'></a>
|
||||||
|
## v20.0.0 (2025-06-05)
|
||||||
|
|
||||||
|
- [Improvement] Test python package distribution build when running make test. (by @Danyal-Faheem)
|
||||||
|
|
||||||
|
- 💥[Feature] Upgrade to teak. (by @Danyal-Faheem)
|
||||||
|
|
||||||
|
<a id='changelog-19.0.4'></a>
|
||||||
|
## v19.0.4 (2025-04-10)
|
||||||
|
|
||||||
|
- [Bugfix] Remove deprecated filter_scopes from import_dashboard script. (by @Danyal-Faheem)
|
||||||
|
|
||||||
|
<a id='changelog-19.0.3'></a>
|
||||||
|
## v19.0.3 (2025-04-03)
|
||||||
|
|
||||||
|
- [Bugfix] Migrate to native filters instead of filter box charts on default course overview dashboard which have been completely deprecated as of superset 4.0.0 release. (by @Danyal-Faheem)
|
||||||
|
|
||||||
|
- [Improvement] Enable Alerts and Reports in superset. (by @Danyal-Faheem)
|
||||||
|
|
||||||
|
- [Improvement] Make superset ports consistent on local and dev by running it on 2247 in both environments. (by @Danyal-Faheem)
|
||||||
|
|
||||||
|
<a id='changelog-19.0.2'></a>
|
||||||
|
## v19.0.2 (2025-03-14)
|
||||||
|
|
||||||
|
- [Bugfix] Do not add cairn-postgresql as a dependency when CAIRN_RUN_POSTGRESQL is false. (by @Danyal-Faheem)
|
||||||
|
- [Bugfix] Add missing CAIRN_POSTGRESQL_HOST and CAIRN_POSTGRESQL_PORT settings to allow usage with external postgresql dbs. (by @Danyal-Faheem)
|
||||||
|
- [Bugfix] Do not manage cairn-clickhouse permissions CAIRN_RUN_CLICKHOUSE is false. (by @Danyal-Faheem)
|
||||||
|
|
||||||
|
<a id='changelog-19.0.1'></a>
|
||||||
|
## v19.0.1 (2025-03-12)
|
||||||
|
|
||||||
|
- [Improvement] Migrate packaging from setup.py/setuptools to pyproject.toml/hatch. (by @Danyal-Faheem)
|
||||||
|
- For more details view tutor core PR: https://github.com/overhangio/tutor/pull/1163
|
||||||
|
|
||||||
|
- [Improvement] Add hatch_build.py in sdist target to fix the installation issues (by @dawoudsheraz)
|
||||||
|
|
||||||
<a id='changelog-19.0.0'></a>
|
<a id='changelog-19.0.0'></a>
|
||||||
## v19.0.0 (2024-10-22)
|
## v19.0.0 (2024-10-22)
|
||||||
|
|
||||||
|
|||||||
24
Makefile
24
Makefile
@ -1,25 +1,30 @@
|
|||||||
.DEFAULT_GOAL := help
|
.DEFAULT_GOAL := help
|
||||||
.PHONY: docs
|
.PHONY: docs
|
||||||
SRC_DIRS = ./tutorcairn
|
SRC_DIRS = ./tutorcairn
|
||||||
BLACK_OPTS = --exclude templates ${SRC_DIRS}
|
|
||||||
|
|
||||||
# Warning: These checks are not necessarily run on every PR.
|
# Warning: These checks are not necessarily run on every PR.
|
||||||
test: test-lint test-types test-format # Run some static checks.
|
test: test-lint test-format test-types test-pythonpackage # Run some static checks.
|
||||||
|
|
||||||
test-format: ## Run code formatting tests
|
test-format: ## Run code formatting tests
|
||||||
black --check --diff $(BLACK_OPTS)
|
ruff format --check --diff ${SRC_DIRS}
|
||||||
|
|
||||||
test-lint: ## Run code linting tests
|
test-lint: ## Run code linting tests
|
||||||
pylint --errors-only --enable=unused-import,unused-argument --ignore=templates --ignore=docs/_ext ${SRC_DIRS}
|
ruff check ${SRC_DIRS}
|
||||||
|
|
||||||
test-types: ## Run type checks.
|
test-types: ## Run type checks.
|
||||||
mypy --exclude=templates --ignore-missing-imports --implicit-reexport --strict ${SRC_DIRS}
|
mypy --exclude=templates --ignore-missing-imports --implicit-reexport --strict ${SRC_DIRS}
|
||||||
|
|
||||||
format: ## Format code automatically
|
build-pythonpackage: ## Build the "tutor-cairn" python package for upload to pypi
|
||||||
black $(BLACK_OPTS)
|
python -m build --sdist
|
||||||
|
|
||||||
isort: ## Sort imports. This target is not mandatory because the output may be incompatible with black formatting. Provided for convenience purposes.
|
test-pythonpackage: build-pythonpackage ## Test that package can be uploaded to pypi
|
||||||
isort --skip=templates ${SRC_DIRS}
|
twine check dist/tutor_cairn-$(shell make version).tar.gz
|
||||||
|
|
||||||
|
format: ## Format code
|
||||||
|
ruff format ${SRC_DIRS}
|
||||||
|
|
||||||
|
fix-lint: ## Fix lint errors automatically
|
||||||
|
ruff check --fix ${SRC_DIRS}
|
||||||
|
|
||||||
changelog-entry: ## Create a new changelog entry.
|
changelog-entry: ## Create a new changelog entry.
|
||||||
scriv create
|
scriv create
|
||||||
@ -27,6 +32,9 @@ changelog-entry: ## Create a new changelog entry.
|
|||||||
changelog: ## Collect changelog entries in the CHANGELOG.md file.
|
changelog: ## Collect changelog entries in the CHANGELOG.md file.
|
||||||
scriv collect
|
scriv collect
|
||||||
|
|
||||||
|
version: ## Print the current tutor-cairn version
|
||||||
|
@python -c 'import io, os; about = {}; exec(io.open(os.path.join("tutorcairn", "__about__.py"), "rt", encoding="utf-8").read(), about); print(about["__version__"])'
|
||||||
|
|
||||||
ESCAPE =
|
ESCAPE =
|
||||||
help: ## Print this help
|
help: ## Print this help
|
||||||
@grep -E '^([a-zA-Z_-]+:.*?## .*|######* .+)$$' Makefile \
|
@grep -E '^([a-zA-Z_-]+:.*?## .*|######* .+)$$' Makefile \
|
||||||
|
|||||||
22
README.rst
22
README.rst
@ -20,15 +20,15 @@ We created a tool to help you answer all these questions. Cairn is a Tutor plugi
|
|||||||
Cairn vs alternatives
|
Cairn vs alternatives
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
========================================== ===== =================================================================================== ===================================================
|
========================================== ===== ==================================================================================== =================================================================================================================== ===================================================
|
||||||
List of features Cairn `Open edX Insights <https://edx.readthedocs.io/projects/edx-insights/en/latest/>`__ `Figures <https://github.com/appsembler/figures>`__
|
List of features Cairn `Aspects <https://docs.openedx.org/projects/openedx-aspects/en/latest/index.html>`__ `Open edX Insights <https://docs.openedx.org/en/latest/site_ops/install_configure_run_guide/insights/index.html>`__ `Figures <https://github.com/appsembler/figures>`__
|
||||||
========================================== ===== =================================================================================== ===================================================
|
========================================== ===== ==================================================================================== =================================================================================================================== ===================================================
|
||||||
Event aggregation ✅ ✅ ❌
|
Event aggregation ✅ ✅ ✅ ❌
|
||||||
Real-time data ✅ ❌ ✅
|
Real-time data ✅ ✅ ❌ ✅
|
||||||
Easy to install ✅ ❌ ✅
|
Easy to install ✅ ✅ ❌ ✅
|
||||||
Custom queries and dashboards ✅ ❌ ❌
|
Custom queries and dashboards ✅ ✅ ❌ ❌
|
||||||
Works with the latest Open edX versions ✅ ✅ ❌
|
Works with the latest Open edX versions ✅ ✅ ✅ ❌
|
||||||
========================================== ===== =================================================================================== ===================================================
|
========================================== ===== ==================================================================================== =================================================================================================================== ===================================================
|
||||||
|
|
||||||
|
|
||||||
How does Cairn work?
|
How does Cairn work?
|
||||||
@ -237,6 +237,8 @@ Postgresql/Superset settings
|
|||||||
- ``CAIRN_RUN_POSTGRESQL`` (default: ``true``): set to ``false`` to run your own Postgresql cluster separately from Cairn. Postgresql is the database that stores all data related to Superset, which is the Cairn frontend.
|
- ``CAIRN_RUN_POSTGRESQL`` (default: ``true``): set to ``false`` to run your own Postgresql cluster separately from Cairn. Postgresql is the database that stores all data related to Superset, which is the Cairn frontend.
|
||||||
- ``CAIRN_SUPERSET_LANGUAGE_CODE`` (default: ``"{{ LANGUAGE_CODE[:2] }}"``): 2-letter code of the default language for the Superset frontend. View the list of all supported languages `here <https://github.com/apache/superset/blob/dc575080d7e43d40b1734bb8f44fdc291cb95b11/superset/config.py#L324>`__. When different than "en", users will have the opportunity to switch from English to this language via a flag icon in the top-right corner.
|
- ``CAIRN_SUPERSET_LANGUAGE_CODE`` (default: ``"{{ LANGUAGE_CODE[:2] }}"``): 2-letter code of the default language for the Superset frontend. View the list of all supported languages `here <https://github.com/apache/superset/blob/dc575080d7e43d40b1734bb8f44fdc291cb95b11/superset/config.py#L324>`__. When different than "en", users will have the opportunity to switch from English to this language via a flag icon in the top-right corner.
|
||||||
- ``CAIRN_SUPERSET_DOCKER_IMAGE`` (default: ``"{{ DOCKER_REGISTRY }}overhangio/cairn-superset:{{ CAIRN_VERSION }}"``): name of the Docker image that runs Postgresql.
|
- ``CAIRN_SUPERSET_DOCKER_IMAGE`` (default: ``"{{ DOCKER_REGISTRY }}overhangio/cairn-superset:{{ CAIRN_VERSION }}"``): name of the Docker image that runs Postgresql.
|
||||||
|
- ``CAIRN_POSTGRESQL_HOST`` (default: ``"cairn-postgresql"``): Host address of the Postgresql database.
|
||||||
|
- ``CAIRN_POSTGRESQL_PORT`` (default: ``5432``): Postgresql port.
|
||||||
- ``CAIRN_POSTGRESQL_DATABASE`` (default: ``"superset"``): name of the Postgresql database.
|
- ``CAIRN_POSTGRESQL_DATABASE`` (default: ``"superset"``): name of the Postgresql database.
|
||||||
- ``CAIRN_POSTGRESQL_USERNAME`` (default: ``"superset"``): Postgresql username.
|
- ``CAIRN_POSTGRESQL_USERNAME`` (default: ``"superset"``): Postgresql username.
|
||||||
- ``CAIRN_POSTGRESQL_PASSWORD`` (default: ``"{{ 20|random_string }}"``): Postgresql password.
|
- ``CAIRN_POSTGRESQL_PASSWORD`` (default: ``"{{ 20|random_string }}"``): Postgresql password.
|
||||||
@ -260,7 +262,7 @@ Then apply changes with::
|
|||||||
Troubleshooting
|
Troubleshooting
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
This Tutor plugin is maintained by Danyal Faheem from `Edly <https://edly.io>`__. Community support is available from the official `Open edX forum <https://discuss.openedx.org>`__. Do you need help with this plugin? See the `troubleshooting <https://docs.tutor.edly.io/troubleshooting.html>`__ section from the Tutor documentation.
|
This Tutor plugin is maintained by Eemaan Amir from `Edly <https://edly.io>`__. Community support is available from the official `Open edX forum <https://discuss.openedx.org>`__. Do you need help with this plugin? See the `troubleshooting <https://docs.tutor.edly.io/troubleshooting.html>`__ section from the Tutor documentation.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
- [Improvement] Migrate packaging from setup.py/setuptools to pyproject.toml/hatch. (by @Danyal-Faheem)
|
|
||||||
- For more details view tutor core PR: https://github.com/overhangio/tutor/pull/1163
|
|
||||||
@ -1 +0,0 @@
|
|||||||
- [Improvement] Add hatch_build.py in sdist target to fix the installation issues (by @dawoudsheraz)
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
- [Improvement] Migrate from pylint and black to ruff. (by @Danyal-Faheem)
|
||||||
@ -8,7 +8,7 @@ authors = [
|
|||||||
{name = "Edly"}, {email = "hello@edly.io"},
|
{name = "Edly"}, {email = "hello@edly.io"},
|
||||||
]
|
]
|
||||||
maintainers = [
|
maintainers = [
|
||||||
{name = "Danyal Faheem"}, {email = "danyal.faheem@arbisoft.com"}
|
{name = "Eemaan Amir"}, {email = "eemaan.amir@arbisoft.com"}
|
||||||
]
|
]
|
||||||
description = "Scalable, real-time analytics for Open edX"
|
description = "Scalable, real-time analytics for Open edX"
|
||||||
readme = {file = "README.rst", content-type = "text/x-rst"}
|
readme = {file = "README.rst", content-type = "text/x-rst"}
|
||||||
@ -25,16 +25,15 @@ classifiers = [
|
|||||||
"Programming Language :: Python :: 3.12",
|
"Programming Language :: Python :: 3.12",
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tutor>=19.0.0,<20.0.0",
|
"tutor>=20.0.0,<21.0.0",
|
||||||
]
|
]
|
||||||
# these fields will be set by hatch_build.py
|
# these fields will be set by hatch_build.py
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
"tutor[dev]>=19.0.0,<20.0.0",
|
"tutor[dev]>=20.0.0,<21.0.0",
|
||||||
"pylint",
|
"ruff",
|
||||||
"black"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.entry-points."tutor.plugin.v1"]
|
[project.entry-points."tutor.plugin.v1"]
|
||||||
@ -65,3 +64,19 @@ exclude = ["tests*"]
|
|||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
[tool.hatch.build.targets.wheel]
|
||||||
packages = ["tutorcairn"]
|
packages = ["tutorcairn"]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
exclude = ["templates", "docs/_ext"]
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
# E: pycodestyle errors
|
||||||
|
# I: isort
|
||||||
|
# N: pep8-naming
|
||||||
|
select = ["E", "I", "N"]
|
||||||
|
|
||||||
|
# F401: unused-import
|
||||||
|
# F841: unused-variable
|
||||||
|
# W292: missing-newline-at-end-of-file
|
||||||
|
extend-select = ["F401", "F841", "W292"]
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
__version__ = "19.0.0"
|
__version__ = "20.0.0"
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# Cairn
|
# Cairn
|
||||||
{{ CAIRN_HOST }}{$default_site_port} {
|
{{ CAIRN_HOST }}{$default_site_port} {
|
||||||
reverse_proxy cairn-superset:8000
|
reverse_proxy cairn-superset:2247
|
||||||
}
|
}
|
||||||
|
|||||||
@ -130,9 +130,9 @@ spec:
|
|||||||
app.kubernetes.io/name: cairn-clickhouse
|
app.kubernetes.io/name: cairn-clickhouse
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: 1000
|
runAsUser: {{ APP_USER_ID }}
|
||||||
runAsGroup: 1000
|
runAsGroup: {{ APP_USER_ID }}
|
||||||
fsGroup: 1000
|
fsGroup: {{ APP_USER_ID }}
|
||||||
fsGroupChangePolicy: "OnRootMismatch"
|
fsGroupChangePolicy: "OnRootMismatch"
|
||||||
containers:
|
containers:
|
||||||
- name: cairn-clickhouse
|
- name: cairn-clickhouse
|
||||||
@ -183,8 +183,8 @@ spec:
|
|||||||
app.kubernetes.io/name: cairn-superset
|
app.kubernetes.io/name: cairn-superset
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: 1000
|
runAsUser: {{ APP_USER_ID }}
|
||||||
runAsGroup: 1000
|
runAsGroup: {{ APP_USER_ID }}
|
||||||
containers:
|
containers:
|
||||||
- name: cairn-superset
|
- name: cairn-superset
|
||||||
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
||||||
@ -227,8 +227,8 @@ spec:
|
|||||||
app.kubernetes.io/name: cairn-superset-worker
|
app.kubernetes.io/name: cairn-superset-worker
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: 1000
|
runAsUser: {{ APP_USER_ID }}
|
||||||
runAsGroup: 1000
|
runAsGroup: {{ APP_USER_ID }}
|
||||||
containers:
|
containers:
|
||||||
- name: cairn-superset-worker
|
- name: cairn-superset-worker
|
||||||
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
||||||
@ -261,8 +261,8 @@ spec:
|
|||||||
app.kubernetes.io/name: cairn-superset-worker-beat
|
app.kubernetes.io/name: cairn-superset-worker-beat
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: 1000
|
runAsUser: {{ APP_USER_ID }}
|
||||||
runAsGroup: 1000
|
runAsGroup: {{ APP_USER_ID }}
|
||||||
containers:
|
containers:
|
||||||
- name: cairn-superset-worker-beat
|
- name: cairn-superset-worker-beat
|
||||||
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
||||||
|
|||||||
@ -10,8 +10,8 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
restartPolicy: Never
|
restartPolicy: Never
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: 1000
|
runAsUser: {{ APP_USER_ID }}
|
||||||
runAsGroup: 1000
|
runAsGroup: {{ APP_USER_ID }}
|
||||||
containers:
|
containers:
|
||||||
- name: cairn-clickhouse
|
- name: cairn-clickhouse
|
||||||
image: {{ CAIRN_CLICKHOUSE_DOCKER_IMAGE }}
|
image: {{ CAIRN_CLICKHOUSE_DOCKER_IMAGE }}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
type: NodePort
|
type: NodePort
|
||||||
ports:
|
ports:
|
||||||
- port: 8000
|
- port: 2247
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
selector:
|
selector:
|
||||||
app.kubernetes.io/name: cairn-superset
|
app.kubernetes.io/name: cairn-superset
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
cairn-clickhouse-job:
|
cairn-clickhouse-job:
|
||||||
image: {{ CAIRN_CLICKHOUSE_DOCKER_IMAGE }}
|
image: {{ CAIRN_CLICKHOUSE_DOCKER_IMAGE }}
|
||||||
user: "1000:1000"
|
user: "{{ APP_USER_ID }}:{{ APP_USER_ID }}"
|
||||||
depends_on: {{ [("cairn-clickhouse", CAIRN_RUN_CLICKHOUSE)]|list_if }}
|
depends_on: {{ [("cairn-clickhouse", CAIRN_RUN_CLICKHOUSE)]|list_if }}
|
||||||
volumes:
|
volumes:
|
||||||
- ../plugins/cairn/apps/clickhouse/auth.json:/scripts/clickhouse-auth.json:ro
|
- ../plugins/cairn/apps/clickhouse/auth.json:/scripts/clickhouse-auth.json:ro
|
||||||
@ -23,7 +23,7 @@ cairn-superset-job:
|
|||||||
disable: true
|
disable: true
|
||||||
depends_on:
|
depends_on:
|
||||||
{% if RUN_REDIS %}- redis{% endif %}
|
{% if RUN_REDIS %}- redis{% endif %}
|
||||||
- cairn-postgresql
|
{% if CAIRN_RUN_POSTGRESQL %}- cairn-postgresql{% endif %}
|
||||||
cairn-openedx-job:
|
cairn-openedx-job:
|
||||||
image: {{ DOCKER_IMAGE_OPENEDX }}
|
image: {{ DOCKER_IMAGE_OPENEDX }}
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
setowner 1000 /data/cairn-clickhouse
|
{% if CAIRN_RUN_CLICKHOUSE %}setowner {{ APP_USER_ID }} /data/cairn-clickhouse{% endif %}
|
||||||
{% if CAIRN_RUN_POSTGRESQL %}setowner 70 /data/cairn-postgresql{% endif %}
|
{% if CAIRN_RUN_POSTGRESQL %}setowner 70 /data/cairn-postgresql{% endif %}
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
- ../../data/cairn/clickhouse:/data/cairn-clickhouse
|
{% if CAIRN_RUN_CLICKHOUSE %}- ../../data/cairn/clickhouse:/data/cairn-clickhouse{% endif %}
|
||||||
{% if CAIRN_RUN_POSTGRESQL %}- ../../data/cairn/postgresql:/data/cairn-postgresql{% endif %}
|
{% if CAIRN_RUN_POSTGRESQL %}- ../../data/cairn/postgresql:/data/cairn-postgresql{% endif %}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ cairn-clickhouse:
|
|||||||
- ../../data/cairn/clickhouse:/var/lib/clickhouse
|
- ../../data/cairn/clickhouse:/var/lib/clickhouse
|
||||||
- ../plugins/cairn/apps/clickhouse/users.d/cairn.xml:/etc/clickhouse-server/users.d/cairn.xml:ro
|
- ../plugins/cairn/apps/clickhouse/users.d/cairn.xml:/etc/clickhouse-server/users.d/cairn.xml:ro
|
||||||
- ../plugins/cairn/apps/clickhouse/auth.json:/scripts/clickhouse-auth.json:ro
|
- ../plugins/cairn/apps/clickhouse/auth.json:/scripts/clickhouse-auth.json:ro
|
||||||
user: "1000:1000"
|
user: "{{ APP_USER_ID }}:{{ APP_USER_ID }}"
|
||||||
environment:
|
environment:
|
||||||
CLICKHOUSE_DO_NOT_CHOWN: "1"
|
CLICKHOUSE_DO_NOT_CHOWN: "1"
|
||||||
ulimits:
|
ulimits:
|
||||||
@ -42,7 +42,7 @@ cairn-superset:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
{% if RUN_REDIS %}- redis{% endif %}
|
{% if RUN_REDIS %}- redis{% endif %}
|
||||||
- cairn-postgresql
|
{% if CAIRN_RUN_POSTGRESQL %}- cairn-postgresql{% endif %}
|
||||||
cairn-superset-worker:
|
cairn-superset-worker:
|
||||||
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
||||||
volumes:
|
volumes:
|
||||||
@ -56,7 +56,7 @@ cairn-superset-worker:
|
|||||||
disable: true
|
disable: true
|
||||||
depends_on:
|
depends_on:
|
||||||
{% if RUN_REDIS %}- redis{% endif %}
|
{% if RUN_REDIS %}- redis{% endif %}
|
||||||
- cairn-postgresql
|
{% if CAIRN_RUN_POSTGRESQL %}- cairn-postgresql{% endif %}
|
||||||
cairn-superset-worker-beat:
|
cairn-superset-worker-beat:
|
||||||
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
image: {{ CAIRN_SUPERSET_DOCKER_IMAGE }}
|
||||||
volumes:
|
volumes:
|
||||||
@ -70,7 +70,7 @@ cairn-superset-worker-beat:
|
|||||||
disable: true
|
disable: true
|
||||||
depends_on:
|
depends_on:
|
||||||
{% if RUN_REDIS %}- redis{% endif %}
|
{% if RUN_REDIS %}- redis{% endif %}
|
||||||
- cairn-postgresql
|
{% if CAIRN_RUN_POSTGRESQL %}- cairn-postgresql{% endif %}
|
||||||
{% if CAIRN_RUN_POSTGRESQL %}
|
{% if CAIRN_RUN_POSTGRESQL %}
|
||||||
cairn-postgresql:
|
cairn-postgresql:
|
||||||
image: docker.io/postgres:9.6-alpine
|
image: docker.io/postgres:9.6-alpine
|
||||||
|
|||||||
@ -25,7 +25,7 @@ config: t.Dict[str, t.Dict[str, t.Any]] = {
|
|||||||
"HOST": "data.{{ LMS_HOST }}",
|
"HOST": "data.{{ LMS_HOST }}",
|
||||||
# Clickhouse
|
# Clickhouse
|
||||||
"RUN_CLICKHOUSE": True,
|
"RUN_CLICKHOUSE": True,
|
||||||
"CLICKHOUSE_DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/cairn-clickhouse:{{ CAIRN_VERSION }}",
|
"CLICKHOUSE_DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/cairn-clickhouse:{{ CAIRN_VERSION }}", # noqa: E501
|
||||||
"CLICKHOUSE_HOST": "cairn-clickhouse",
|
"CLICKHOUSE_HOST": "cairn-clickhouse",
|
||||||
"CLICKHOUSE_HTTP_PORT": 8123,
|
"CLICKHOUSE_HTTP_PORT": 8123,
|
||||||
"CLICKHOUSE_HTTP_SCHEME": "http",
|
"CLICKHOUSE_HTTP_SCHEME": "http",
|
||||||
@ -34,9 +34,11 @@ config: t.Dict[str, t.Dict[str, t.Any]] = {
|
|||||||
"CLICKHOUSE_USERNAME": "openedx",
|
"CLICKHOUSE_USERNAME": "openedx",
|
||||||
# Superset/Postgresql
|
# Superset/Postgresql
|
||||||
"RUN_POSTGRESQL": True,
|
"RUN_POSTGRESQL": True,
|
||||||
|
"POSTGRESQL_HOST": "cairn-postgresql",
|
||||||
|
"POSTGRESQL_PORT": "5432",
|
||||||
"POSTGRESQL_DATABASE": "superset",
|
"POSTGRESQL_DATABASE": "superset",
|
||||||
"POSTGRESQL_USERNAME": "superset",
|
"POSTGRESQL_USERNAME": "superset",
|
||||||
"SUPERSET_DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/cairn-superset:{{ CAIRN_VERSION }}",
|
"SUPERSET_DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/cairn-superset:{{ CAIRN_VERSION }}", # noqa: E501
|
||||||
"SUPERSET_LANGUAGE_CODE": "{{ LANGUAGE_CODE[:2] }}",
|
"SUPERSET_LANGUAGE_CODE": "{{ LANGUAGE_CODE[:2] }}",
|
||||||
# SSO
|
# SSO
|
||||||
"ENABLE_SSO": True,
|
"ENABLE_SSO": True,
|
||||||
@ -140,7 +142,7 @@ def _print_superset_host(
|
|||||||
@click.option(
|
@click.option(
|
||||||
"-p",
|
"-p",
|
||||||
"--password",
|
"--password",
|
||||||
help="Specify password from the command line. If undefined, no password will be set. (Ignored with SSO)",
|
help="Specify password from the command line. If undefined, no password will be set. (Ignored with SSO)", # noqa: E501
|
||||||
hide_input=True,
|
hide_input=True,
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
@ -179,7 +181,7 @@ def create_user_command(
|
|||||||
if bootstrap_dashboards:
|
if bootstrap_dashboards:
|
||||||
yield (
|
yield (
|
||||||
"cairn-superset",
|
"cairn-superset",
|
||||||
f"python ./superset/cairn/ctl.py bootstrap-dashboards {username} /app/bootstrap/courseoverview.json",
|
f"python ./superset/cairn/ctl.py bootstrap-dashboards {username} /app/bootstrap/courseoverview.json", # noqa: E501
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,9 @@ import requests
|
|||||||
# https://mysqlclient.readthedocs.io/user_guide.html#mysql-c-api-function-mapping
|
# https://mysqlclient.readthedocs.io/user_guide.html#mysql-c-api-function-mapping
|
||||||
from MySQLdb._mysql import escape_string as sql_escape_string
|
from MySQLdb._mysql import escape_string as sql_escape_string
|
||||||
|
|
||||||
import lms.startup
|
import django
|
||||||
|
|
||||||
lms.startup.run()
|
django.setup()
|
||||||
|
|
||||||
from lms.djangoapps.courseware.courses import get_course
|
from lms.djangoapps.courseware.courses import get_course
|
||||||
from xmodule.modulestore.django import modulestore
|
from xmodule.modulestore.django import modulestore
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -11,7 +11,7 @@ from superset.cairn import sso as cairn_sso
|
|||||||
|
|
||||||
# https://superset.apache.org/docs/installation/configuring-superset
|
# https://superset.apache.org/docs/installation/configuring-superset
|
||||||
SECRET_KEY = "{{ CAIRN_SUPERSET_SECRET_KEY }}"
|
SECRET_KEY = "{{ CAIRN_SUPERSET_SECRET_KEY }}"
|
||||||
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{{ CAIRN_POSTGRESQL_USERNAME }}:{{ CAIRN_POSTGRESQL_PASSWORD }}@cairn-postgresql/{{ CAIRN_POSTGRESQL_DATABASE }}"
|
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{{ CAIRN_POSTGRESQL_USERNAME }}:{{ CAIRN_POSTGRESQL_PASSWORD }}@{{ CAIRN_POSTGRESQL_HOST }}:{{ CAIRN_POSTGRESQL_PORT }}/{{ CAIRN_POSTGRESQL_DATABASE }}"
|
||||||
|
|
||||||
# Caddy is running behind a proxy: Superset needs to handle x-forwarded-* headers
|
# Caddy is running behind a proxy: Superset needs to handle x-forwarded-* headers
|
||||||
# https://flask.palletsprojects.com/en/latest/deploying/proxy_fix/
|
# https://flask.palletsprojects.com/en/latest/deploying/proxy_fix/
|
||||||
@ -126,9 +126,9 @@ AUTH_ROLES_SYNC_AT_LOGIN = {{ CAIRN_AUTH_ROLES_SYNC_AT_LOGIN }}
|
|||||||
AUTH_USER_REGISTRATION = True
|
AUTH_USER_REGISTRATION = True
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
class CeleryConfig: # pylint: disable=too-few-public-methods
|
class CeleryConfig:
|
||||||
BROKER_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB}"
|
BROKER_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB}"
|
||||||
CELERY_IMPORTS = ("superset.sql_lab", "superset.tasks")
|
CELERY_IMPORTS = ("superset.sql_lab", "superset.tasks","superset.tasks.thumbnails",)
|
||||||
CELERYD_LOG_LEVEL = "DEBUG"
|
CELERYD_LOG_LEVEL = "DEBUG"
|
||||||
CELERYD_PREFETCH_MULTIPLIER = 1
|
CELERYD_PREFETCH_MULTIPLIER = 1
|
||||||
CELERY_ACKS_LATE = False
|
CELERY_ACKS_LATE = False
|
||||||
@ -142,10 +142,6 @@ class CeleryConfig: # pylint: disable=too-few-public-methods
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
CELERYBEAT_SCHEDULE = {
|
CELERYBEAT_SCHEDULE = {
|
||||||
"email_reports.schedule_hourly": {
|
|
||||||
"task": "email_reports.schedule_hourly",
|
|
||||||
"schedule": crontab(minute=1, hour="*"),
|
|
||||||
},
|
|
||||||
"reports.scheduler": {
|
"reports.scheduler": {
|
||||||
"task": "reports.scheduler",
|
"task": "reports.scheduler",
|
||||||
"schedule": crontab(minute="*", hour="*"),
|
"schedule": crontab(minute="*", hour="*"),
|
||||||
@ -159,13 +155,32 @@ class CeleryConfig: # pylint: disable=too-few-public-methods
|
|||||||
|
|
||||||
CELERY_CONFIG = CeleryConfig
|
CELERY_CONFIG = CeleryConfig
|
||||||
|
|
||||||
|
# Email configuration
|
||||||
|
SMTP_HOST = "{{ SMTP_HOST }}"
|
||||||
|
SMTP_PORT = {{ SMTP_PORT }}
|
||||||
|
SMTP_STARTTLS = {{ SMTP_USE_TLS }}
|
||||||
|
SMTP_SSL = {{ SMTP_USE_SSL }}
|
||||||
|
SMTP_USER = "{{ SMTP_USERNAME }}" # use the empty string "" if using an unauthenticated SMTP server
|
||||||
|
SMTP_PASSWORD = "{{ SMTP_PASSWORD }}" # use the empty string "" if using an unauthenticated SMTP server
|
||||||
|
SMTP_MAIL_FROM = "{{ CONTACT_EMAIL }}"
|
||||||
|
EMAIL_REPORTS_SUBJECT_PREFIX = "[{{ PLATFORM_NAME }}] "
|
||||||
|
|
||||||
|
ALERT_REPORTS_NOTIFICATION_DRY_RUN = False
|
||||||
|
WEBDRIVER_BASEURL = "http://cairn-superset:2247/"
|
||||||
|
# The base URL for the email report hyperlinks.
|
||||||
|
WEBDRIVER_BASEURL_USER_FRIENDLY = "{{ CAIRN_HOST }}"
|
||||||
|
|
||||||
# Avoid duplicate logging because of propagation to root logger
|
# Avoid duplicate logging because of propagation to root logger
|
||||||
logging.getLogger("superset").propagate = False
|
logging.getLogger("superset").propagate = False
|
||||||
|
|
||||||
# https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md
|
# https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md
|
||||||
FEATURE_FLAGS = {
|
FEATURE_FLAGS = {
|
||||||
# Enable dashboard embedding
|
# Enable dashboard embedding
|
||||||
"EMBEDDED_SUPERSET": True
|
"EMBEDDED_SUPERSET": True,
|
||||||
|
# This feature is stable but known to have bugs from time to time
|
||||||
|
# Alerts and Reports also do not work on arm64 base images
|
||||||
|
"ALERT_REPORTS": True,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENABLE_CORS=True
|
ENABLE_CORS=True
|
||||||
|
|||||||
@ -7,16 +7,34 @@ FROM docker.io/apache/superset:4.0.0
|
|||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
|
# https://github.com/apache/superset/blob/4.0.0/Dockerfile#L109-L110
|
||||||
|
# Extracted from https://superset.apache.org/docs/installation/alerts-reports/#custom-dockerfile
|
||||||
|
ARG GECKODRIVER_VERSION=v0.33.0 \
|
||||||
|
FIREFOX_VERSION=117.0.1
|
||||||
|
|
||||||
|
RUN apt-get update -qq \
|
||||||
|
&& apt-get install -yqq --no-install-recommends \
|
||||||
|
libnss3 \
|
||||||
|
libdbus-glib-1-2 \
|
||||||
|
libgtk-3-0 \
|
||||||
|
libx11-xcb1 \
|
||||||
|
libasound2 \
|
||||||
|
libxtst6 \
|
||||||
|
wget \
|
||||||
|
pkg-config \
|
||||||
|
# Install GeckoDriver WebDriver
|
||||||
|
&& wget -q https://github.com/mozilla/geckodriver/releases/download/${GECKODRIVER_VERSION}/geckodriver-${GECKODRIVER_VERSION}-linux64.tar.gz -O - | tar xfz - -C /usr/local/bin \
|
||||||
|
# Install Firefox
|
||||||
|
&& wget -q https://download-installer.cdn.mozilla.net/pub/firefox/releases/${FIREFOX_VERSION}/linux-x86_64/en-US/firefox-${FIREFOX_VERSION}.tar.bz2 -O - | tar xfj - -C /opt \
|
||||||
|
&& ln -s /opt/firefox/firefox /usr/local/bin/firefox \
|
||||||
|
&& apt-get autoremove -yqq --purge wget && rm -rf /var/[log,tmp]/* /tmp/* /var/lib/apt/lists/*
|
||||||
|
|
||||||
# https://pypi.org/project/clickhouse-driver/
|
# https://pypi.org/project/clickhouse-driver/
|
||||||
# https://pypi.org/project/mysqlclient/
|
# https://pypi.org/project/mysqlclient/
|
||||||
# https://pypi.org/project/clickhouse-connect/
|
# https://pypi.org/project/clickhouse-connect/
|
||||||
# https://pypi.org/project/clickhouse-sqlalchemy/
|
# https://pypi.org/project/clickhouse-sqlalchemy/
|
||||||
# https://pypi.org/project/Authlib/
|
# https://pypi.org/project/Authlib/
|
||||||
# We preserve the clickhouse-sqlalchemy package to keep backward compatibility with existing dashboards
|
# We preserve the clickhouse-sqlalchemy package to keep backward compatibility with existing dashboards
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y \
|
|
||||||
pkg-config
|
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip,sharing=shared pip install \
|
RUN --mount=type=cache,target=/root/.cache/pip,sharing=shared pip install \
|
||||||
clickhouse-driver==0.2.7 \
|
clickhouse-driver==0.2.7 \
|
||||||
mysqlclient==2.2.4 \
|
mysqlclient==2.2.4 \
|
||||||
@ -30,11 +48,11 @@ USER superset
|
|||||||
COPY --chown=superset:superset ./cairn /app/superset/cairn
|
COPY --chown=superset:superset ./cairn /app/superset/cairn
|
||||||
|
|
||||||
# This is required to have a proper healthcheck
|
# This is required to have a proper healthcheck
|
||||||
ENV SUPERSET_PORT=8000
|
ENV SUPERSET_PORT=2247
|
||||||
|
|
||||||
ENTRYPOINT []
|
ENTRYPOINT []
|
||||||
CMD gunicorn \
|
CMD gunicorn \
|
||||||
--bind "0.0.0.0:8000" \
|
--bind "0.0.0.0:2247" \
|
||||||
--access-logfile '-' \
|
--access-logfile '-' \
|
||||||
--error-logfile '-' \
|
--error-logfile '-' \
|
||||||
--workers 2 \
|
--workers 2 \
|
||||||
|
|||||||
@ -229,20 +229,6 @@ def import_dashboard(data, user, database):
|
|||||||
|
|
||||||
# Update filter mapping
|
# Update filter mapping
|
||||||
metadata = json.loads(dashboard.json_metadata)
|
metadata = json.loads(dashboard.json_metadata)
|
||||||
new_filter_scopes = {}
|
|
||||||
for old_slice_id, filter_scope in metadata["filter_scopes"].items():
|
|
||||||
new_filter_scope = {}
|
|
||||||
for filter_name, properties in filter_scope.items():
|
|
||||||
properties["immune"] = [
|
|
||||||
old_to_new_slice_id_map[old_immune_id]
|
|
||||||
for old_immune_id in properties["immune"]
|
|
||||||
]
|
|
||||||
new_filter_scope[filter_name] = properties
|
|
||||||
# Note that filter scope keys are str, not int
|
|
||||||
new_filter_scopes[
|
|
||||||
str(old_to_new_slice_id_map[int(old_slice_id)])
|
|
||||||
] = new_filter_scope
|
|
||||||
metadata["filter_scopes"] = new_filter_scopes
|
|
||||||
dashboard.json_metadata = json.dumps(metadata)
|
dashboard.json_metadata = json.dumps(metadata)
|
||||||
|
|
||||||
# Load dashboard
|
# Load dashboard
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user