Compare commits

...

27 Commits

Author SHA1 Message Date
Florian du Garage Num
1a9977e454 remove hard-coded uid 1000
Some checks failed
Sync with private repo / sync (push) Has been cancelled
Run tests / tests (3.12) (push) Has been cancelled
Run tests / tests (3.9) (push) Has been cancelled
2025-09-30 21:41:58 +02:00
Eemaan Amir
10701f4e64
chore: update maintainer email (#70) 2025-09-19 11:51:14 +05:00
Danyal Faheem
8f4a0b1d91
feat: migrate from pylint/black to ruff (#69)
Linked Epic: https://github.com/overhangio/tutor/issues/1251

Some new rules that have been added are:

I: sort imports
N: check for pep8-naming standards
W292: check for missing extra line at EOF

Some of our lines, particularly in config, break the 88 character line length limit. For that, we add a # noqa: E501 to let ruff know to ignore the rule for that line
2025-08-05 15:42:29 +05:00
Ahmed Khalid
65802e8741
Merge pull request #68 from overhangio/teak 2025-06-27 17:21:06 +05:00
Syed Muhammad Dawoud Sheraz Ali
4647d8a01a chore: update changelog for v20 2025-06-26 22:23:09 +05:00
Danyal-Faheem
3bc0733e6e chore: create update changelog date 2025-06-26 22:21:32 +05:00
Danyal-Faheem
26d00745c8 v20.0.0 2025-06-26 22:21:32 +05:00
Edly
065397496c Merge remote-tracking branch 'origin/release' 2025-05-20 12:30:16 +00:00
Danyal Faheem
5d30333587
test: verify python package distribution build when running make test (#65)
* test: python package distribution build when running make test
Pushing to pypi would occasionally fail because of breaking distribution build.
We verify the build in the github CI now so that we can mitigate those errors later on.
2025-05-20 17:29:13 +05:00
Overhang.IO
a18d74c5b6 Merge remote-tracking branch 'origin/release' 2025-04-10 06:23:38 +00:00
Danyal Faheem
1e86feb8ae
v19.0.4 (#67) 2025-04-10 11:22:37 +05:00
Overhang.IO
863babcecf Merge remote-tracking branch 'origin/release' 2025-04-10 06:10:55 +00:00
Danyal Faheem
a4c4b6b158
fix: remove deprecated filter_scopes from import_dashboard script (#66)
Reference issue: https://github.com/overhangio/tutor-cairn/pull/53/files\#r2034772248
Filter_scopes have been deprecated as of Superset 4.0.0
We have also migrated away from filter box to native filters as of #53.
2025-04-10 11:09:53 +05:00
Overhang.IO
0e0b7e5103 Merge remote-tracking branch 'origin/release' 2025-04-08 14:21:17 +00:00
Danyal Faheem
0c033e2a9a
fix: breaking docs due to incompatible table borders (#64)
We also add a column in the cairn comparison with other analytics tools table to showcase aspects and its features.
2025-04-08 19:20:09 +05:00
Overhang.IO
41a4b119d1 Merge remote-tracking branch 'origin/release' 2025-04-08 07:03:08 +00:00
Danyal Faheem
b6d0b6e6be
v19.0.3 (#62) 2025-04-08 12:00:11 +05:00
Sarina Canelake
01edb2a7df
docs: Update edx.rtd links to docs.openedx.org (#63) 2025-04-08 11:59:45 +05:00
Overhang.IO
ce8fd488aa Merge remote-tracking branch 'origin/release' 2025-04-03 07:45:35 +00:00
Danyal Faheem
2c1492169c
feat: enable alerts and reports in superset (#54)
* feat: enable alerts and reports in superset
fixes #46
2025-04-03 12:43:03 +05:00
Overhang.IO
50277142c7 Merge remote-tracking branch 'origin/release' 2025-04-03 07:42:01 +00:00
Danyal Faheem
d5015a0860
fix: make superset ports consistent in local and dev (#61)
Superset was running on 2247 port in dev mode and on 8000 in local mode
We now make this consistent so that superset runs on 2247 in both local and dev
2025-04-03 12:40:55 +05:00
Danyal Faheem
acd14969de
fix: lms.startup -> django.setup in import courses script (#60)
lms.startup has been removed as of https://github.com/openedx/edx-platform/pull/36302
Therefore, we move to the original django.setup now
2025-03-26 17:00:37 +05:00
Danyal Faheem
16d018625f
fix: migrate to native filters on default course overview dashboard from filter box charts (#53) 2025-03-25 19:14:17 +05:00
Danyal Faheem
1d10b3afc4
v19.0.2 (#58) 2025-03-14 18:11:01 +05:00
Danyal Faheem
04f4275236
fix: do not add cairn-postgresql and cairn-clickhouse dependencies when they are running externally (#57)
* fix: don't add cairn-postgresql as a dependency when CAIRN_RUN_POSTGRESQL is false

* fix: don't manage cairn-clickhouse permissions CAIRN_RUN_CLICKHOUSE is false

* fix: add missing CAIRN_POSTGRESQL_HOST and CAIRN_POSTGRESQL_PORT settings to allow usage with external postgresql DBs
2025-03-14 17:48:06 +05:00
Danyal Faheem
a6026d6f6b
v19.0.1 (#56) 2025-03-13 14:07:26 +05:00
23 changed files with 165 additions and 107 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 \

View File

@ -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
------- -------

View File

@ -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

View File

@ -1 +0,0 @@
- [Improvement] Add hatch_build.py in sdist target to fix the installation issues (by @dawoudsheraz)

View File

@ -0,0 +1 @@
- [Improvement] Migrate from pylint and black to ruff. (by @Danyal-Faheem)

View File

@ -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]

View File

@ -1 +1 @@
__version__ = "19.0.0" __version__ = "20.0.0"

View File

@ -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
} }

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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

View File

@ -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:

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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

View File

@ -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
) )

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -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