Régis Behmo 5bf17dda91 feat: upgrade to Palm
This upgrade includes SSO login. Finally! We can now login to Superset
via the LMS. Thanks to OARS for providing the base security manager
implementation!
2023-06-15 00:13:57 +02:00

192 lines
5.6 KiB
Python

from __future__ import annotations
from glob import glob
import os
import shlex
import typing as t
import click
import pkg_resources
from tutor import hooks
from .__about__ import __version__
HERE = os.path.abspath(os.path.dirname(__file__))
hooks.Filters.CONFIG_UNIQUE.add_items(
[
("CAIRN_CLICKHOUSE_PASSWORD", "{{ 20|random_string }}"),
("CAIRN_POSTGRESQL_PASSWORD", "{{ 20|random_string }}"),
("CAIRN_SUPERSET_SECRET_KEY", "{{ 20|random_string }}"),
("CAIRN_SSO_CLIENT_SECRET", "{{ 20|random_string }}"),
]
)
hooks.Filters.CONFIG_DEFAULTS.add_items(
[
("CAIRN_VERSION", __version__),
("CAIRN_DOCKER_HOST_SOCK_PATH", "/var/run/docker.sock"),
("CAIRN_HOST", "data.{{ LMS_HOST }}"),
# Clickhouse
("CAIRN_RUN_CLICKHOUSE", True),
(
"CAIRN_CLICKHOUSE_DOCKER_IMAGE",
"{{ DOCKER_REGISTRY }}overhangio/cairn-clickhouse:{{ CAIRN_VERSION }}",
),
("CAIRN_CLICKHOUSE_HOST", "cairn-clickhouse"),
("CAIRN_CLICKHOUSE_HTTP_PORT", 8123),
("CAIRN_CLICKHOUSE_HTTP_SCHEME", "http"),
("CAIRN_CLICKHOUSE_PORT", 9000),
("CAIRN_CLICKHOUSE_DATABASE", "openedx"),
("CAIRN_CLICKHOUSE_USERNAME", "openedx"),
# Superset/Postgresql
("CAIRN_RUN_POSTGRESQL", True),
("CAIRN_POSTGRESQL_DATABASE", "superset"),
("CAIRN_POSTGRESQL_USERNAME", "superset"),
(
"CAIRN_SUPERSET_DOCKER_IMAGE",
"{{ DOCKER_REGISTRY }}overhangio/cairn-superset:{{ CAIRN_VERSION }}",
),
("CAIRN_SUPERSET_LANGUAGE_CODE", "{{ LANGUAGE_CODE[:2] }}"),
# SSO
("CAIRN_ENABLE_SSO", True),
("CAIRN_SSO_CLIENT_ID", "cairn"),
# Vector
# https://hub.docker.com/r/timberio/vector/tags
# https://github.com/vectordotdev/vector/releases
("CAIRN_VECTOR_DOCKER_IMAGE", "docker.io/timberio/vector:0.25.1-alpine"),
]
)
# Init scripts
for service in ["cairn-clickhouse", "cairn-superset", "cairn-openedx"]:
with open(
os.path.join(HERE, "templates", "cairn", "tasks", service, "init"),
encoding="utf-8",
) as fi:
task = fi.read()
hooks.Filters.CLI_DO_INIT_TASKS.add_item((service, task))
# Docker images
hooks.Filters.IMAGES_BUILD.add_items(
[
(
"cairn-clickhouse",
("plugins", "cairn", "build", "cairn-clickhouse"),
"{{ CAIRN_CLICKHOUSE_DOCKER_IMAGE }}",
(),
),
(
"cairn-superset",
("plugins", "cairn", "build", "cairn-superset"),
"{{ CAIRN_SUPERSET_DOCKER_IMAGE }}",
(),
),
]
)
hooks.Filters.IMAGES_PULL.add_items(
[
(
"cairn-clickhouse",
"{{ CAIRN_CLICKHOUSE_DOCKER_IMAGE }}",
),
(
"cairn-superset",
"{{ CAIRN_SUPERSET_DOCKER_IMAGE }}",
),
]
)
hooks.Filters.IMAGES_PUSH.add_items(
[
(
"cairn-superset",
"{{ CAIRN_SUPERSET_DOCKER_IMAGE }}",
),
(
"cairn-clickhouse",
"{{ CAIRN_CLICKHOUSE_DOCKER_IMAGE }}",
),
]
)
@hooks.Filters.APP_PUBLIC_HOSTS.add()
def _print_superset_host(hosts: list[str], context_name: t.Literal["local", "dev"]):
if context_name == "dev":
hosts.append("{{ CAIRN_HOST }}:2247")
else:
hosts.append("{{ CAIRN_HOST }}")
return hosts
@click.command(
name="cairn-createuser", help="Create a Cairn user, both in Clickhouse and Superset"
)
@click.option(
"--bootstrap-dashboards",
is_flag=True,
help="Load the default Cairn dashboards to the user's Superset account",
)
@click.option("--admin", is_flag=True)
@click.option(
"-p",
"--password",
help="Specify password from the command line. If undefined, no password will be set. (Ignored with SSO)",
hide_input=True,
)
@click.option(
"-c",
"--course-id",
"course_ids",
help="Limit access to a selection of courses (Ignored with SSO).",
multiple=True,
hide_input=True,
)
@click.argument("username")
@click.argument("email")
def create_user_command(
bootstrap_dashboards: bool, admin: bool, password: str, course_ids: list[str], username: str, email: str
) -> t.Iterable[tuple[str, str]]:
admin_opt = " --admin" if admin else ""
# TODO can we now simplify the clickhouse image?
# - get rid of the cairn utility
# - remove the auth.json file
create_superset_user = "python ./superset/cairn/ctl.py createuser"
if password:
create_superset_user += f" --password={shlex.quote(password)}"
for course_id in course_ids:
create_superset_user += f" --course-id={course_id}"
create_superset_user += f" {admin_opt} {username} {email}"
yield ("cairn-superset", create_superset_user)
# Bootstrap dashboards
if bootstrap_dashboards:
yield (
"cairn-superset",
f"python ./superset/cairn/ctl.py bootstrap-dashboards {username} /app/bootstrap/courseoverview.json",
)
hooks.Filters.CLI_DO_COMMANDS.add_item(create_user_command)
####### Boilerplate code
# Add the "templates" folder as a template root
hooks.Filters.ENV_TEMPLATE_ROOTS.add_item(
pkg_resources.resource_filename("tutorcairn", "templates")
)
# Render the "build" and "apps" folders
hooks.Filters.ENV_TEMPLATE_TARGETS.add_items(
[
("cairn/build", "plugins"),
("cairn/apps", "plugins"),
],
)
# Load patches from files
for path in glob(
os.path.join(pkg_resources.resource_filename("tutorcairn", "patches"), "*")
):
with open(path, encoding="utf-8") as patch_file:
hooks.Filters.ENV_PATCHES.add_item((os.path.basename(path), patch_file.read()))