From 8af27458901cdc2d57b3de4708fec0efd97cc875 Mon Sep 17 00:00:00 2001 From: Henrry Pulgarin <39854568+Henrrypg@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:30:10 -0500 Subject: [PATCH] feat: add auto generated jobs (#87) --- README.md | 128 ++++++++++++++ README.rst | 85 ---------- drydock/hooks.py | 15 ++ drydock/patches/k8s-jobs | 15 ++ drydock/patches/kustomization | 21 +-- drydock/patches/kustomization-resources | 8 +- drydock/plugin.py | 157 +++++++++++++++++- .../drydock/k8s/debug/deployments.yml | 4 + .../templates/drydock/k8s/debug/ingress.yml | 1 + .../drydock/k8s/drydock-jobs/cms.yml | 62 ------- .../drydock/k8s/drydock-jobs/forum.yml | 46 ----- .../drydock/k8s/drydock-jobs/lms.yml | 83 --------- .../drydock/k8s/drydock-jobs/minio.yml | 38 ----- .../drydock/k8s/drydock-jobs/mongodb.yml | 52 ------ .../drydock/k8s/drydock-jobs/mysql.yml | 48 ------ .../drydock/k8s/drydock-jobs/notes.yml | 132 --------------- .../templates/drydock/k8s/forum-overrides.yml | 0 drydock/templates/drydock/k8s/jobs.yml | 113 +++++++++++++ .../drydock/k8s/patches/hpa-sync-wave.yml | 8 + .../post-init-deployments-sync-wave.yml | 6 + .../drydock/k8s/patches/sync-wave-4.yml | 6 - .../drydock/k8s/patches/sync-wave-5.yml | 6 - drydock/templates/drydock/task/mongodb/init | 25 +++ 23 files changed, 471 insertions(+), 588 deletions(-) create mode 100644 README.md delete mode 100644 README.rst create mode 100644 drydock/hooks.py create mode 100644 drydock/patches/k8s-jobs delete mode 100644 drydock/templates/drydock/k8s/drydock-jobs/cms.yml delete mode 100644 drydock/templates/drydock/k8s/drydock-jobs/forum.yml delete mode 100644 drydock/templates/drydock/k8s/drydock-jobs/lms.yml delete mode 100644 drydock/templates/drydock/k8s/drydock-jobs/minio.yml delete mode 100644 drydock/templates/drydock/k8s/drydock-jobs/mongodb.yml delete mode 100644 drydock/templates/drydock/k8s/drydock-jobs/mysql.yml delete mode 100644 drydock/templates/drydock/k8s/drydock-jobs/notes.yml delete mode 100644 drydock/templates/drydock/k8s/forum-overrides.yml create mode 100644 drydock/templates/drydock/k8s/jobs.yml create mode 100644 drydock/templates/drydock/k8s/patches/hpa-sync-wave.yml create mode 100644 drydock/templates/drydock/k8s/patches/post-init-deployments-sync-wave.yml delete mode 100644 drydock/templates/drydock/k8s/patches/sync-wave-4.yml delete mode 100644 drydock/templates/drydock/k8s/patches/sync-wave-5.yml create mode 100644 drydock/templates/drydock/task/mongodb/init diff --git a/README.md b/README.md new file mode 100644 index 00000000..c6cd238e --- /dev/null +++ b/README.md @@ -0,0 +1,128 @@ +Drydock +======= + +Drydock is an opinionated tool offering a set of Tutor plugins aiming to provide features that enhance the operation of OpenedX installations in Kubernetes. It is developed by [Edunext](https://www.edunext.co/). + +- A set of Kubernetes Jobs that replace the current tutor jobs with [ArgoCD Sync Waves](https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/) that allow for a more controlled deployment of openedx. +- A set of Kustomization overrides adding [ArgoCD Sync Waves](https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/) annotations to needed additional resources such as debug, workers or hpa. +- Backup cronjobs that allow backup of the MySQL and MongoDB databases. +- Integration of New Relic monitoring +- Add flower deployment for Celery +- Add a custom nginx and cert-manager configuration +- Add a set of debug resources to help diagnose issues + +Extra plugins added: + +- A patch that allows for the tuning of celery workers via `DRYDOCK_ENABLE_CELERY_TUNING` +- Allows caddy to catch requests for multiple domains through `DRYDOCK_ENABLE_MULTITENANCY` +- Add scorm matcher to caddy through `DRYDOCK_ENABLE_SCORM` +- A patch that allows for the use of sentry via `DRYDOCK_ENABLE_SENTRY` and `DRYDOCK_SENTRY_DSN` +- Patch for cms and lms worker pods to allow pod probes and lifecycle to work properly. Enabled via `DRYDOCK_POD_LIFECYCLE` + +Installation +------------ + +``` bash +tvm plugins install -e git+https://github.com/edunext/drydock#egg=drydock +tutor plugins enable drydock +tutor config save +``` + +Getting started +--------------- + +``` bash +tutor config save +``` + +Configuration +------------- + +The following configuration options are available: + +- `DRYDOCK_INIT_JOBS`: Whether run the initialization jobs or not. Defaults to `false`. +- `DRYDOCK_CMS_SSO_USER`: The username of the CMS SSO user. Defaults to `cms`. +- `DRYDOCK_AUTO_TLS`: Whether to use cert-manager to automatically generate TLS certificates. Defaults to `false`. +- `DRYDOCK_FLOWER`: Whether to deploy a flower deployment for celery. Defaults to `false`. +- `DRYDOCK_INGRESS`: Whether to deploy an ingress for the LMS and CMS. Defaults to `false`. +- `DRYDOCK_INGRESS_EXTRA_HOSTS`: A list of extra hosts to add to the ingress. Defaults to `[]`. +- `DRYDOCK_CUSTOM_CERTS`: A dictionary of custom certificates to use with cert-manager. Defaults to `{}`. +- `DRYDOCK_NEWRELIC_LICENSE_KEY`: The New Relic license key. Defaults to `""`. +- `DRYDOCK_DEBUG`: Whether to deploy debug resources. Defaults to `false`. +- `DRYDOCK_ENABLE_CELERY_TUNING`: Whether to enable celery tuning. Defaults to `true`. +- `DRYDOCK_ENABLE_MULTITENANCY`: Whether to enable multitennacy. Defaults to `true`. +- `DRYDOCK_ENABLE_SCORM`: Whether to enable scorm. Defaults to `true`. +- `DRYDOCK_ENABLE_SENTRY`: Whether to enable sentry. Defaults to `true`. +- `DRYDOCK_SENTRY_DSN`: The sentry DSN. Defaults to `""`. +- `DRYDOCK_POD_LIFECYCLE`: Whether to enable pod lifecycle. Defaults to `true`. +- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_MFE`: The minimum available percentage for the MFE's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. +- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_FORUM`: The minimum available percentage for the FORUM's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. +- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_CADDY`: The minimum available percentage for the CADDY's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. +- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_LMS`: The minimum available percentage for the LMS's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. +- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_LMS_WORKER`: The minimum available percentage for the LMS WORKER's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. +- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_CMS`: The minimum available percentage for the CMS's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. +- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_CMS_WORKER`: The minimum available percentage for the worker's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. +- `DRYDOCK_MIGRATE_FROM`: it allows defining the version of the OpenedX platform we are migrating from. It accepts the integer value mapping the origin release, for instance, `13`(maple) or `14`(nutmeg). When this variable is set, a group of `release-specific upgrade jobs` are added to the Kubernetes manifests. These jobs are applied to the cluster in a suitable order (thanks to the GitOps implementation with ArgoCD + sync waves) to guarantee the correct behavior of the platform in the new version. This brings the `tutor k8s upgrade `_ command to the GitOps pattern. The release-specific upgrade jobs are supported from release `13`(maple). Defaults to `0` (which disables release-specific upgrade jobs) + +> **_NOTE:_** You also need to set `DRYDOCK_INIT_JOBS` to `true` to enable the release-specific upgrade jobs in the case of a platform migration. + +Job generation +-------------- + +Tutor doesn't generate manifest files for the initialization jobs, in consequence we can't use GitOps tools like ArgoCD to deploy the initialization jobs. + +We had been using a static definition of the initialization jobs, but now we are using the `Tutor filters `_ to generate the kubernetes definition of the initialization jobs. This is a big improvement because now we can add new initialization jobs without modifying the Drydock code. The jobs are taken from `COMMANDS_PRE_INIT`, `COMMANDS_INIT` and `CLI_DO_INIT_TASKS` Filters. + +ArgoCD Sync Waves Support +----------------------- + +[Tutor filter](https://docs.tutor.edly.io/reference/api/hooks/filters.html) **SYNC_WAVES_ORDER** was added to allow define [ArgoCD Sync Waves](https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/) order and apply to the kubernetes resources through **get_sync_waves_for_resource** function. + +We are defined by defult the following order: + +1. `All kubernetes resources` (except the ones that are defined in the next waves) +2. `Initialization Jobs` +3. `Upgrade Jobs`: When **DRYDOCK_MIGRATE_FROM** is set, over the Sync Wave 50 +4. `CMS and LMS Deployments`: When **DRYDOCK_POD_LIFECYCLE** is active, over the Sync Wave 100 +5. `Debug Resources`: When **DRYDOCK_DEBUG** active, over the Sync Wave 100 +6. `Horizontal Pod Autoscalers`: When active, over the Sync Wave 150 + +Workaround to upgrade from Maple to Palm or later +------------------------------------------------- + +> **_NOTE:_** Quince uses Django 4.2 which only supports MySQL 8 or higher. You must upgrade your version of MySQL prior to performing the upgrade. + +The upgrade from Maple to Palm fails because an issue with a squashed migration in [edx-enterprise](https://github.com/openedx/edx-enterprise/blob/3.61.11/integrated_channels/blackboard/migrations/0001_initial_squashed_0014_alter_blackboardlearnerassessmentdatatransmissionaudit_enterprise_course_enrollment_id.py). To go around this issue, we need to apply migrations using an older version of edx-enterprise (3.60.4). + +1. Run the sync to Palm without enabling the init jobs or upgrade jobs. + +2. Once the LMS Deployment is running in the Palm version, go inside a pod and run the following: + + ``` bash + pip install edx-enterprise==3.60.4 + ./manage.py lms migrate + pip install edx-enterprise==3.61.11 + ``` + +3. Now, you can enable the init jobs and upgrade jobs and run the sync again. + +This workaround references the [Andrey's comment](https://discuss.openedx.org/t/updating-tutor-lilac-to-palm-now-that-palms-released-fails/10557/23) + +Rationale +--------- + +This project is proposed as a possible way of creating a community maintained +reference for large openedx installation. +Sometimes the needs for customization in large instances of openedx goes +against the required simplicity in the configuration that the tutor project +strives for. In those cases, the solution is to create a tutor plugin that +allows for such advanced customization options. + +This projects intends to fill that gap with a solution that should allow many +community members to collaborate in one repo on the heavy toll that is the +maintainance of openedx operations. + +License +------- + +This software is licensed under the terms of the AGPLv3. diff --git a/README.rst b/README.rst deleted file mode 100644 index d5248e38..00000000 --- a/README.rst +++ /dev/null @@ -1,85 +0,0 @@ -Drydock -======= - -Drydock is an opinionated tool offering a set of Tutor plugins aiming to provide features that enhance the operation of OpenedX installations in Kubernetes. It is developed by `Edunext `_ - - -- A set of Kubernetes Jobs that replace the current tutor jobs with `ArgoCD Sync Waves `_ that allow for a more controlled deployment of openedx. -- A set of Kustomization overrides adding `ArgoCD Sync Waves `_ annotations to needed additional resources such as debug, workers or hpa. -- Backup cronjobs that allow backup of the MySQL and MongoDB databases. -- Integration of New Relic monitoring -- Add flower deployment for Celery -- Add a custom nginx and cert-manager configuration -- Add a set of debug resources to help diagnose issues - -Extra plugins added: - -- A patch that allows for the tuning of celery workers via `DRYDOCK_ENABLE_CELERY_TUNING` -- Allows caddy to catch requests for multiple domains through `DRYDOCK_ENABLE_MULTITENANCY` -- Add scorm matcher to caddy through `DRYDOCK_ENABLE_SCORM` -- A patch that allows for the use of sentry via `DRYDOCK_ENABLE_SENTRY` and `DRYDOCK_SENTRY_DSN` -- Patch for cms and lms worker pods to allow pod probes and lifecycle to work properly. Enabled via `DRYDOCK_POD_LIFECYCLE` - -Installation ------------- - -.. code-block:: bash - - tvm plugins install -e git+https://github.com/edunext/drydock#egg=drydock - tutor plugins enable drydock - tutor config save - -Getting started ---------------- - -.. code-block:: bash - - tutor config save - - -Configuration -------------- - -The following configuration options are available: - -- `DRYDOCK_INIT_JOBS`: Whether run the initialization jobs or not. Defaults to `false`. -- `DRYDOCK_CMS_SSO_USER`: The username of the CMS SSO user. Defaults to `cms`. -- `DRYDOCK_AUTO_TLS`: Whether to use cert-manager to automatically generate TLS certificates. Defaults to `false`. -- `DRYDOCK_FLOWER`: Whether to deploy a flower deployment for celery. Defaults to `false`. -- `DRYDOCK_INGRESS`: Whether to deploy an ingress for the LMS and CMS. Defaults to `false`. -- `DRYDOCK_INGRESS_EXTRA_HOSTS`: A list of extra hosts to add to the ingress. Defaults to `[]`. -- `DRYDOCK_CUSTOM_CERTS`: A dictionary of custom certificates to use with cert-manager. Defaults to `{}`. -- `DRYDOCK_NEWRELIC_LICENSE_KEY`: The New Relic license key. Defaults to `""`. -- `DRYDOCK_DEBUG`: Whether to deploy debug resources. Defaults to `false`. -- `DRYDOCK_ENABLE_CELERY_TUNING` : Whether to enable celery tuning. Defaults to `true`. -- `DRYDOCK_ENABLE_MULTITENANCY` : Whether to enable multitennacy. Defaults to `true`. -- `DRYDOCK_ENABLE_SCORM` : Whether to enable scorm. Defaults to `true`. -- `DRYDOCK_ENABLE_SENTRY` : Whether to enable sentry. Defaults to `true`. -- `DRYDOCK_SENTRY_DSN` : The sentry DSN. Defaults to `""`. -- `DRYDOCK_POD_LIFECYCLE` : Whether to enable pod lifecycle. Defaults to `true`. -- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_MFE` : The minimum available percentage for the MFE's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. -- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_FORUM` : The minimum available percentage for the FORUM's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. -- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_CADDY` : The minimum available percentage for the CADDY's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. -- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_LMS` : The minimum available percentage for the LMS's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. -- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_LMS_WORKER` : The minimum available percentage for the LMS WORKER's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. -- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_CMS` : The minimum available percentage for the CMS's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. -- `DRYDOCK_PDB_MINAVAILABLE_PERCENTAGE_CMS_WORKER` : The minimum available percentage for the worker's PodDisruptionBudget. To disable the PodDisruptionBudget, set `0`. Defaults to `0`. - -Rationale ---------- - -This project is proposed as a possible way of creating a community maintained -reference for large openedx installation. -Sometimes the needs for customization in large instances of openedx goes -against the required simplicity in the configuration that the tutor project -strives for. In those cases, the solution is to create a tutor plugin that -allows for such advanced customization options. - -This projects intends to fill that gap with a solution that should allow many -community members to collaborate in one repo on the heavy toll that is the -maintainance of openedx operations. - -License -------- - -This software is licensed under the terms of the AGPLv3. diff --git a/drydock/hooks.py b/drydock/hooks.py new file mode 100644 index 00000000..d888f8c2 --- /dev/null +++ b/drydock/hooks.py @@ -0,0 +1,15 @@ +""" +These hooks are stored in a separate module. If they were included in plugin.py, then +the pod-autoscaling hooks would be created in the context of some other plugin that imports +them. +""" + +from __future__ import annotations + +import typing as t + +from tutor.core.hooks import Filter + +SYNC_WAVES_ORDER_ATTRS_TYPE = t.Dict[str, int] + +SYNC_WAVES_ORDER: Filter[dict[str, SYNC_WAVES_ORDER_ATTRS_TYPE], []] = Filter() diff --git a/drydock/patches/k8s-jobs b/drydock/patches/k8s-jobs new file mode 100644 index 00000000..dc33a214 --- /dev/null +++ b/drydock/patches/k8s-jobs @@ -0,0 +1,15 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: mongodb-job + labels: + app.kubernetes.io/component: job +spec: + ttlSecondsAfterFinished: 100 + template: + spec: + restartPolicy: Never + containers: + - name: mongodb + image: {{ DOCKER_IMAGE_MONGODB }} diff --git a/drydock/patches/kustomization b/drydock/patches/kustomization index f5c4bddf..3d9558fc 100644 --- a/drydock/patches/kustomization +++ b/drydock/patches/kustomization @@ -13,21 +13,14 @@ patches: kind: Job labelSelector: app.kubernetes.io/component=job path: plugins/drydock/k8s/patches/tutor-jobs.yml -# Patch the sync waves -- target: - kind: Deployment - name: "lms|cms|lms-worker|cms-worker|forum" - path: plugins/drydock/k8s/patches/sync-wave-4.yml -{%- if DRYDOCK_DEBUG is defined and DRYDOCK_DEBUG %} -- target: - kind: Deployment|Ingress|Service - name: "cms-debug|lms-debug|ingress-debug" - path: plugins/drydock/k8s/patches/sync-wave-5.yml -{%- endif %} -- target: - kind: HorizontalPodAutoscaler - path: plugins/drydock/k8s/patches/sync-wave-5.yml {% if DRYDOCK_ENABLE_CELERY_TUNING %} - path: plugins/drydock/k8s/celery/cms-worker.yml - path: plugins/drydock/k8s/celery/lms-worker.yml {% endif -%} +- target: + kind: HorizontalPodAutoscaler + path: plugins/drydock/k8s/patches/hpa-sync-wave.yml +- target: + kind: Deployment + name: '{% for name in DRYDOCK_POST_INIT_DEPLOYMENTS %}{{ name }}{% if not loop.last %}|{% endif %}{% endfor %}' + path: plugins/drydock/k8s/patches/post-init-deployments-sync-wave.yml diff --git a/drydock/patches/kustomization-resources b/drydock/patches/kustomization-resources index 13cda057..de1ffcf1 100644 --- a/drydock/patches/kustomization-resources +++ b/drydock/patches/kustomization-resources @@ -1,13 +1,7 @@ - plugins/drydock/k8s/multipurpose-jobs.yml - plugins/drydock/k8s/pdb/openedx-pdb.yml {%- if DRYDOCK_INIT_JOBS %} -- plugins/drydock/k8s/drydock-jobs/mysql.yml -- plugins/drydock/k8s/drydock-jobs/mongodb.yml -- plugins/drydock/k8s/drydock-jobs/lms.yml -- plugins/drydock/k8s/drydock-jobs/cms.yml -- plugins/drydock/k8s/drydock-jobs/minio.yml -- plugins/drydock/k8s/drydock-jobs/forum.yml -- plugins/drydock/k8s/drydock-jobs/notes.yml +- plugins/drydock/k8s/jobs.yml {%- endif %} {% if DRYDOCK_FLOWER -%} - plugins/drydock/k8s/flower.yml diff --git a/drydock/plugin.py b/drydock/plugin.py index 78297b0c..48bb173f 100644 --- a/drydock/plugin.py +++ b/drydock/plugin.py @@ -1,11 +1,127 @@ from glob import glob +import functools import os +import click import pkg_resources -from tutor import hooks +import typing as t + +from .hooks import SYNC_WAVES_ORDER_ATTRS_TYPE, SYNC_WAVES_ORDER + +from tutor import hooks as tutor_hooks +from tutor import env as tutor_env +from tutor import serialize, types +from tutor import config as tutor_config from .__about__ import __version__ +INIT_JOBS_SYNC_WAVE = 1 + +# This function is taken from +# https://github.com/overhangio/tutor/blob/v16.1.8/tutor/commands/k8s.py#L182 +def _load_jobs(tutor_conf: types.Config) -> t.Iterable[t.Any]: + jobs = tutor_env.render_file(tutor_conf, "k8s", "jobs.yml").strip() + for manifest in serialize.load_all(jobs): + if manifest["kind"] == "Job": + yield manifest + + +# The definition of the init tasks is taken and adapted from +# https://github.com/overhangio/tutor/blob/v16.1.8/tutor/commands/jobs.py#L65 +# and https://github.com/overhangio/tutor/blob/v16.1.8/tutor/commands/k8s.py#L82 +def get_init_tasks(): + """Return the list of init tasks to run.""" + init_tasks = list(tutor_hooks.Filters.CLI_DO_INIT_TASKS.iterate()) + context = click.get_current_context().obj + tutor_conf = tutor_config.load(context.root) + + for i, (service, command) in enumerate(init_tasks): + for template in _load_jobs(tutor_conf): + if template['metadata']['name'] != service + '-job': + continue + + render_command = tutor_env.render_str(tutor_conf, command) + + template['metadata']['name'] = 'drydock-' + template['metadata']['name'] + '-' + str(i) + template['metadata']['labels'].update({ + 'app.kubernetes.io/component': 'drydock-job', + 'drydock.io/target-service': template['metadata']['name'], + 'drydock.io/runner-service': template['metadata']['name'] + }) + template['metadata']['annotations'] = { + 'argocd.argoproj.io/sync-wave': INIT_JOBS_SYNC_WAVE + i * 2, + 'argocd.argoproj.io/hook': 'Sync', + 'argocd.argoproj.io/hook-delete-policy': 'HookSucceeded,BeforeHookCreation' + } + + shell_command = ["sh", "-e", "-c"] + if template["spec"]["template"]["spec"]["containers"][0].get("command") == []: + # In some cases, we need to bypass the container entrypoint. + # Unfortunately, AFAIK, there is no way to do so in K8s manifests. So we mark + # some jobs with "command: []". For these jobs, the entrypoint becomes "sh -e -c". + # We do not do this for every job, because some (most) entrypoints are actually useful. + template["spec"]["template"]["spec"]["containers"][0]["command"] = shell_command + container_args = [render_command] + else: + container_args = shell_command + [render_command] + + template["spec"]["template"]["spec"]["containers"][0]["args"] = container_args + template["spec"]["backoffLimit"] = 1 + template["spec"]["ttlSecondsAfterFinished"] = 3600 + + yield serialize.dumps(template) + + +CORE_SYNC_WAVES_ORDER: SYNC_WAVES_ORDER_ATTRS_TYPE = { + "drydock-upgrade-lms-job": 50, + "drydock-upgrade-cms-job": 51, + "lms-debug": 50, + "cms-debug": 50, + "ingress-debug": 200, + "deployments:post-init-apps": 100, + "horizontalpodautoscalers:all": 150 +} + + +@SYNC_WAVES_ORDER.add() +def _add_core_sync_waves_order(sync_waves_config: SYNC_WAVES_ORDER_ATTRS_TYPE) -> SYNC_WAVES_ORDER_ATTRS_TYPE: + sync_waves_config.update(CORE_SYNC_WAVES_ORDER) + return sync_waves_config + + +@functools.lru_cache(maxsize=None) +def get_sync_waves_order() -> SYNC_WAVES_ORDER_ATTRS_TYPE: + """ + This function is cached for performance. + """ + return SYNC_WAVES_ORDER.apply({}) + + +@tutor_hooks.Actions.PLUGIN_LOADED.add() +def _clear_sync_waves_order_cache(_name: str) -> None: + """ + Don't forget to clear cache, or we'll have some strange surprises... + """ + get_sync_waves_order.cache_clear() + + +def iter_sync_waves_order() -> t.Iterable[SYNC_WAVES_ORDER_ATTRS_TYPE]: + """ + Yield: + (name, dict) + """ + yield from get_sync_waves_order().items() + + +def get_sync_waves_for_resource(resource_name: str) -> SYNC_WAVES_ORDER_ATTRS_TYPE: + """ + Args: + resource_name: the name of the resource + Returns: + dict + """ + return get_sync_waves_order().get(resource_name, 0) + ################# Configuration config = { @@ -15,6 +131,7 @@ "INIT_JOBS": False, "CMS_SSO_USER": "cms", "AUTO_TLS": True, + "MIGRATE_FROM": 0, "FLOWER": False, "INGRESS": False, "INGRESS_EXTRA_HOSTS": [], @@ -38,6 +155,13 @@ "PDB_MINAVAILABLE_PERCENTAGE_MFE": 0, "PDB_MINAVAILABLE_PERCENTAGE_FORUM": 0, "PDB_MINAVAILABLE_PERCENTAGE_CADDY": 0, + "POST_INIT_DEPLOYMENTS": [ + "lms", + "cms", + "forum", + "lms-worker", + "cms-worker", + ], }, # Add here settings that don't have a reasonable default for all users. For # instance: passwords, secret keys, etc. @@ -49,8 +173,8 @@ }, } -hooks.Filters.CONFIG_DEFAULTS.add_items([("OPENEDX_DEBUG_COOKIE", "ednx_enable_debug")]) -hooks.Filters.CONFIG_OVERRIDES.add_items([ +tutor_hooks.Filters.CONFIG_DEFAULTS.add_items([("OPENEDX_DEBUG_COOKIE", "ednx_enable_debug")]) +tutor_hooks.Filters.CONFIG_OVERRIDES.add_items([ # This values are not prefixed with DRYDOCK_ ("MONGODB_ROOT_USERNAME", ""), ("MONGODB_ROOT_PASSWORD", ""), @@ -61,10 +185,10 @@ ################# except maybe for educational purposes :) # Plugin templates -hooks.Filters.ENV_TEMPLATE_ROOTS.add_item( +tutor_hooks.Filters.ENV_TEMPLATE_ROOTS.add_item( pkg_resources.resource_filename("drydock", "templates") ) -hooks.Filters.ENV_TEMPLATE_TARGETS.add_items( +tutor_hooks.Filters.ENV_TEMPLATE_TARGETS.add_items( [ ("drydock/build", "plugins"), ("drydock/apps", "plugins"), @@ -79,19 +203,34 @@ ) ): with open(path, encoding="utf-8") as patch_file: - hooks.Filters.ENV_PATCHES.add_item((os.path.basename(path), patch_file.read())) + tutor_hooks.Filters.ENV_PATCHES.add_item((os.path.basename(path), patch_file.read())) # Load all configuration entries -hooks.Filters.CONFIG_DEFAULTS.add_items( +tutor_hooks.Filters.CONFIG_DEFAULTS.add_items( [ (f"DRYDOCK_{key}", value) for key, value in config["defaults"].items() ] ) -hooks.Filters.CONFIG_UNIQUE.add_items( +tutor_hooks.Filters.CONFIG_UNIQUE.add_items( [ (f"DRYDOCK_{key}", value) for key, value in config["unique"].items() ] ) -hooks.Filters.CONFIG_OVERRIDES.add_items(list(config["overrides"].items())) +tutor_hooks.Filters.CONFIG_OVERRIDES.add_items(list(config["overrides"].items())) + +tutor_hooks.Filters.ENV_TEMPLATE_VARIABLES.add_items( + [ + ('get_init_tasks', get_init_tasks), + ('iter_sync_waves_order', iter_sync_waves_order), + ('get_sync_waves_for_resource', get_sync_waves_for_resource), + ] +) + +# # init script +with open( + pkg_resources.resource_filename("drydock", "templates/drydock/task/mongodb/init"), + encoding="utf-8", +) as fi: + tutor_hooks.Filters.CLI_DO_INIT_TASKS.add_item(("mongodb", fi.read()), priority=tutor_hooks.priorities.HIGH) diff --git a/drydock/templates/drydock/k8s/debug/deployments.yml b/drydock/templates/drydock/k8s/debug/deployments.yml index 256e87a2..724431ae 100644 --- a/drydock/templates/drydock/k8s/debug/deployments.yml +++ b/drydock/templates/drydock/k8s/debug/deployments.yml @@ -5,6 +5,8 @@ metadata: name: cms-debug labels: app.kubernetes.io/name: cms-debug + annotations: + argocd.argoproj.io/sync-wave: "{{ get_sync_waves_for_resource('cms-debug') }}" spec: selector: matchLabels: @@ -57,6 +59,8 @@ metadata: name: lms-debug labels: app.kubernetes.io/name: lms-debug + annotations: + argocd.argoproj.io/sync-wave: "{{ get_sync_waves_for_resource('lms-debug') }}" spec: selector: matchLabels: diff --git a/drydock/templates/drydock/k8s/debug/ingress.yml b/drydock/templates/drydock/k8s/debug/ingress.yml index 4f244a51..ad748cf5 100644 --- a/drydock/templates/drydock/k8s/debug/ingress.yml +++ b/drydock/templates/drydock/k8s/debug/ingress.yml @@ -4,6 +4,7 @@ metadata: name: ingress-debug namespace: {{ K8S_NAMESPACE }} annotations: + argocd.argoproj.io/sync-wave: "{{ get_sync_waves_for_resource('ingress-debug') }}" kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-by-cookie: {{ OPENEDX_DEBUG_COOKIE }} diff --git a/drydock/templates/drydock/k8s/drydock-jobs/cms.yml b/drydock/templates/drydock/k8s/drydock-jobs/cms.yml deleted file mode 100644 index 4c52239c..00000000 --- a/drydock/templates/drydock/k8s/drydock-jobs/cms.yml +++ /dev/null @@ -1,62 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: drydock-cms-job - labels: - drydock.io/component: job - drydock.io/target-service: cms - drydock.io/runner-service: cms - annotations: - argocd.argoproj.io/sync-wave: "3" - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - ttlSecondsAfterFinished: 100 - template: - spec: - restartPolicy: Never - containers: - - name: cms - image: {{ DOCKER_IMAGE_OPENEDX }} - command: - - /bin/sh - - -c - - -e - args: - - | - dockerize -wait tcp://{{ MYSQL_HOST }}:{{ MYSQL_PORT }} -timeout 20s - - echo "Loading settings $DJANGO_SETTINGS_MODULE" - - ./manage.py cms migrate - - # Fix incorrect uploaded file path - if [ -d /openedx/data/uploads/ ]; then - if [ -n "$(ls -A /openedx/data/uploads/)" ]; then - echo "Migrating CMS uploaded files to shared directory" - mv /openedx/data/uploads/* /openedx/media/ - rm -rf /openedx/data/uploads/ - fi - fi - env: - - name: SERVICE_VARIANT - value: cms - - name: DJANGO_SETTINGS_MODULE - value: cms.envs.tutor.production - volumeMounts: - - mountPath: /openedx/edx-platform/lms/envs/tutor/ - name: settings-lms - - mountPath: /openedx/edx-platform/cms/envs/tutor/ - name: settings-cms - - mountPath: /openedx/config - name: config - volumes: - - name: settings-lms - configMap: - name: openedx-settings-lms - - name: settings-cms - configMap: - name: openedx-settings-cms - - name: config - configMap: - name: openedx-config diff --git a/drydock/templates/drydock/k8s/drydock-jobs/forum.yml b/drydock/templates/drydock/k8s/drydock-jobs/forum.yml deleted file mode 100644 index 2a649b19..00000000 --- a/drydock/templates/drydock/k8s/drydock-jobs/forum.yml +++ /dev/null @@ -1,46 +0,0 @@ -{%- if FORUM_DOCKER_IMAGE is defined %} -apiVersion: batch/v1 -kind: Job -metadata: - name: drydock-forum-job - labels: - drydock.io/component: job - drydock.io/target-service: forum - drydock.io/runner-service: forum - annotations: - argocd.argoproj.io/sync-wave: "2" - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - ttlSecondsAfterFinished: 100 - template: - spec: - restartPolicy: Never - containers: - - name: forum - image: {{ FORUM_DOCKER_IMAGE }} - args: - - sh - - -e - - -c - - 'bundle exec rake search:initialize - - bundle exec rake search:rebuild_indices' - env: - - name: SEARCH_SERVER - value: "{{ ELASTICSEARCH_SCHEME }}://{{ ELASTICSEARCH_HOST }}:{{ ELASTICSEARCH_PORT }}" - - name: MONGODB_AUTH - value: "{% if MONGODB_USERNAME and MONGODB_PASSWORD %}{{ MONGODB_USERNAME}}:{{ MONGODB_PASSWORD }}@{% endif %}" - - name: MONGODB_HOST - value: "{{ MONGODB_HOST }}" - - name: MONGODB_PORT - value: "{{ MONGODB_PORT }}" - - name: MONGODB_DATABASE - value: "{{ FORUM_MONGODB_DATABASE }}" - - name: MONGOID_USE_SSL - value: "{{ 'true' if MONGODB_USE_SSL else 'false' }}" - - name: MONGOID_AUTH_SOURCE - value: "{{ MONGODB_AUTH_SOURCE }}" - - name: MONGOID_AUTH_MECH - value: "{{ MONGODB_AUTH_MECHANISM|auth_mech_as_ruby }}" -{%- endif %} diff --git a/drydock/templates/drydock/k8s/drydock-jobs/lms.yml b/drydock/templates/drydock/k8s/drydock-jobs/lms.yml deleted file mode 100644 index ba1985cd..00000000 --- a/drydock/templates/drydock/k8s/drydock-jobs/lms.yml +++ /dev/null @@ -1,83 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: drydock-lms-job - labels: - drydock.io/component: job - drydock.io/target-service: lms - drydock.io/runner-service: lms - annotations: - argocd.argoproj.io/sync-wave: "2" - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - ttlSecondsAfterFinished: 100 - template: - spec: - restartPolicy: Never - containers: - - name: lms - image: {{ DOCKER_IMAGE_OPENEDX }} - command: - - /bin/sh - - -c - - -e - args: - - | - dockerize -wait tcp://{{ MYSQL_HOST }}:{{ MYSQL_PORT }} -timeout 20s - {%- if MONGODB_HOST.startswith("mongodb+srv://") %} - echo "MongoDB is using SRV records, so we cannot wait for it to be ready" - {%- else %} - dockerize -wait tcp://{{ MONGODB_HOST }}:{{ MONGODB_PORT }} -timeout 20s - {%- endif %} - - echo "Loading settings $DJANGO_SETTINGS_MODULE" - - ./manage.py lms migrate - - # Create oauth2 apps for CMS SSO - # https://github.com/openedx/edx-platform/blob/master/docs/guides/studio_oauth.rst - ./manage.py lms manage_user {{ DRYDOCK_CMS_SSO_USER }} {{ DRYDOCK_CMS_SSO_USER }}@openedx --unusable-password - ./manage.py lms create_dot_application \ - --grant-type authorization-code \ - --redirect-uris "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ CMS_HOST }}/complete/edx-oauth2/" \ - --client-id {{ CMS_OAUTH2_KEY_SSO }} \ - --client-secret {{ CMS_OAUTH2_SECRET }} \ - --scopes user_id \ - --skip-authorization \ - --update cms-sso {{ DRYDOCK_CMS_SSO_USER }} - - # Fix incorrect uploaded file path - if [ -d /openedx/data/uploads/ ]; then - if [ -n "$(ls -A /openedx/data/uploads/)" ]; then - echo "Migrating LMS uploaded files to shared directory" - mv /openedx/data/uploads/* /openedx/media/ - rm -rf /openedx/data/uploads/ - fi - fi - - # Create waffle switches to enable some features, if they have not been explicitly defined before - # Completion tracking: add green ticks to every completed unit - (./manage.py lms waffle_switch --list | grep completion.enable_completion_tracking) || ./manage.py lms waffle_switch --create completion.enable_completion_tracking on - env: - - name: SERVICE_VARIANT - value: lms - - name: DJANGO_SETTINGS_MODULE - value: lms.envs.tutor.production - volumeMounts: - - mountPath: /openedx/edx-platform/lms/envs/tutor/ - name: settings-lms - - mountPath: /openedx/edx-platform/cms/envs/tutor/ - name: settings-cms - - mountPath: /openedx/config - name: config - volumes: - - name: settings-lms - configMap: - name: openedx-settings-lms - - name: settings-cms - configMap: - name: openedx-settings-cms - - name: config - configMap: - name: openedx-config diff --git a/drydock/templates/drydock/k8s/drydock-jobs/minio.yml b/drydock/templates/drydock/k8s/drydock-jobs/minio.yml deleted file mode 100644 index f593e2c6..00000000 --- a/drydock/templates/drydock/k8s/drydock-jobs/minio.yml +++ /dev/null @@ -1,38 +0,0 @@ -{%- if MINIO_DOCKER_IMAGE is defined %} -apiVersion: batch/v1 -kind: Job -metadata: - name: drydock-minio-job - labels: - drydock.io/component: job - drydock.io/target-service: minio - drydock.io/runner-service: minio - annotations: - argocd.argoproj.io/sync-wave: "1" - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - ttlSecondsAfterFinished: 100 - template: - spec: - restartPolicy: Never - containers: - - name: minio - image: {{ MINIO_MC_DOCKER_IMAGE }} - command: - - /bin/sh - - -c - - -e - args: - - | - mc config host add minio http://minio:9000 {{ OPENEDX_AWS_ACCESS_KEY }} {{ OPENEDX_AWS_SECRET_ACCESS_KEY }} --api s3v4 - mc mb --ignore-existing minio/{{ MINIO_BUCKET_NAME }} minio/{{ MINIO_FILE_UPLOAD_BUCKET_NAME }} minio/{{ MINIO_VIDEO_UPLOAD_BUCKET_NAME }} - - # Make common file upload bucket public (e.g: for forum image upload) - mc policy set public minio/{{ MINIO_BUCKET_NAME }} - env: - - name: MINIO_ROOT_USER - value: "{{ OPENEDX_AWS_ACCESS_KEY }}" - - name: MINIO_ROOT_PASSWORD - value: "{{ OPENEDX_AWS_SECRET_ACCESS_KEY }}" -{%- endif %} diff --git a/drydock/templates/drydock/k8s/drydock-jobs/mongodb.yml b/drydock/templates/drydock/k8s/drydock-jobs/mongodb.yml deleted file mode 100644 index 73e00097..00000000 --- a/drydock/templates/drydock/k8s/drydock-jobs/mongodb.yml +++ /dev/null @@ -1,52 +0,0 @@ - -apiVersion: batch/v1 -kind: Job -metadata: - name: drydock-mongodb-job - labels: - drydock.io/component: job - drydock.io/target-service: mongodb - drydock.io/runner-service: mongodb - annotations: - argocd.argoproj.io/sync-wave: "1" - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - ttlSecondsAfterFinished: 100 - template: - spec: - restartPolicy: Never - containers: - - name: mongodb - image: {{ DOCKER_IMAGE_MONGODB }} - command: - - /bin/sh - - -c - - -e - args: - - | - echo "Initialising MongoDB..." - mongo --host {{MONGODB_HOST }} {% if MONGODB_ROOT_USERNAME and MONGODB_ROOT_PASSWORD %} -u {{ MONGODB_ROOT_USERNAME }} -p {{ MONGODB_ROOT_PASSWORD }} {% endif %} admin <&2 - exit 1 - fi - sleep 10 - done - echo "MySQL is up and running" - - # edx-platform database - mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "CREATE DATABASE IF NOT EXISTS {{ OPENEDX_MYSQL_DATABASE }};" - mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "CREATE USER IF NOT EXISTS '{{ OPENEDX_MYSQL_USERNAME }}';" - mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "ALTER USER '{{ OPENEDX_MYSQL_USERNAME }}'@'%' IDENTIFIED BY '{{ OPENEDX_MYSQL_PASSWORD }}';" - mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "GRANT ALL ON {{ OPENEDX_MYSQL_DATABASE }}.* TO '{{ OPENEDX_MYSQL_USERNAME }}'@'%';" - {{ patch("drydock-mysql-init-job")|indent(10) }} diff --git a/drydock/templates/drydock/k8s/drydock-jobs/notes.yml b/drydock/templates/drydock/k8s/drydock-jobs/notes.yml deleted file mode 100644 index ac2bb846..00000000 --- a/drydock/templates/drydock/k8s/drydock-jobs/notes.yml +++ /dev/null @@ -1,132 +0,0 @@ -{%- if NOTES_DOCKER_IMAGE is defined %} -apiVersion: batch/v1 -kind: Job -metadata: - name: drydock-notes-job-mysql - labels: - drydock.io/component: job - drydock.io/target-service: notes - drydock.io/runner-service: mysql - annotations: - argocd.argoproj.io/sync-wave: "1" - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - ttlSecondsAfterFinished: 100 - template: - spec: - restartPolicy: Never - containers: - - name: notes - image: {{ DOCKER_IMAGE_MYSQL }} - command: - - /bin/sh - - -c - - -e - args: - - | - mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e 'CREATE DATABASE IF NOT EXISTS {{ NOTES_MYSQL_DATABASE }};' - mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "CREATE USER IF NOT EXISTS '{{ NOTES_MYSQL_USERNAME }}';" - mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "ALTER USER '{{ NOTES_MYSQL_USERNAME }}'@'%' IDENTIFIED BY '{{ NOTES_MYSQL_PASSWORD }}';" - mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "GRANT ALL ON {{ NOTES_MYSQL_DATABASE }}.* TO '{{ NOTES_MYSQL_USERNAME }}'@'%';" ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: drydock-notes-job - labels: - drydock.io/component: job - drydock.io/target-service: notes - drydock.io/runner-service: notes - annotations: - argocd.argoproj.io/sync-wave: "3" - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - ttlSecondsAfterFinished: 100 - template: - spec: - restartPolicy: Never - containers: - - name: notes - image: {{ NOTES_DOCKER_IMAGE }} - command: - - /bin/sh - - -c - - -e - args: [./manage.py migrate] - env: - - name: DJANGO_SETTINGS_MODULE - value: notesserver.settings.tutor - volumeMounts: - - mountPath: /app/edx-notes-api/notesserver/settings/tutor.py - name: settings - subPath: tutor.py - volumes: - - name: settings - configMap: - name: notes-settings ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: drydock-notes-job-lms - labels: - drydock.io/component: job - drydock.io/target-service: notes - drydock.io/runner-service: lms - annotations: - argocd.argoproj.io/sync-wave: "3" - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - ttlSecondsAfterFinished: 100 - template: - spec: - restartPolicy: Never - containers: - - name: notes - image: {{ DOCKER_IMAGE_OPENEDX }} - command: - - /bin/sh - - -c - - -e - args: - - | - # Modify users created an incorrect email and that might clash with the newly created users - ./manage.py lms shell -c \ - "from django.contrib.auth import get_user_model;\ - get_user_model().objects.filter(username='notes').exclude(email='notes@openedx').update(email='notes@openedx')" - - ./manage.py lms manage_user notes notes@openedx --staff --superuser - ./manage.py lms create_dot_application \ - notes \ - notes \ - --redirect-uris "http://notes:8000" \ - --skip-authorization \ - --client-id notes \ - --client-secret "{{ NOTES_OAUTH2_SECRET }}" \ - --update - env: - - name: SERVICE_VARIANT - value: lms - - name: DJANGO_SETTINGS_MODULE - value: lms.envs.tutor.production - volumeMounts: - - mountPath: /openedx/edx-platform/lms/envs/tutor/ - name: settings-lms - - mountPath: /openedx/edx-platform/cms/envs/tutor/ - name: settings-cms - - mountPath: /openedx/config - name: config - volumes: - - name: settings-lms - configMap: - name: openedx-settings-lms - - name: settings-cms - configMap: - name: openedx-settings-cms - - name: config - configMap: - name: openedx-config -{%- endif %} diff --git a/drydock/templates/drydock/k8s/forum-overrides.yml b/drydock/templates/drydock/k8s/forum-overrides.yml deleted file mode 100644 index e69de29b..00000000 diff --git a/drydock/templates/drydock/k8s/jobs.yml b/drydock/templates/drydock/k8s/jobs.yml new file mode 100644 index 00000000..a733df71 --- /dev/null +++ b/drydock/templates/drydock/k8s/jobs.yml @@ -0,0 +1,113 @@ +{% for job in get_init_tasks() %} +{{ job }} +--- +{% endfor %} +{% if DRYDOCK_MIGRATE_FROM %} +apiVersion: batch/v1 +kind: Job +metadata: + name: drydock-upgrade-lms-job + labels: + drydock.io/component: job + drydock.io/target-service: lms + drydock.io/runner-service: lms + annotations: + argocd.argoproj.io/sync-wave: "{{ get_sync_waves_for_resource('drydock-upgrade-lms-job') }}" + argocd.argoproj.io/hook: Sync + argocd.argoproj.io/hook-delete-policy: HookSucceeded +spec: + ttlSecondsAfterFinished: 100 + template: + spec: + restartPolicy: Never + containers: + - name: lms + image: {{ DOCKER_IMAGE_OPENEDX }} + command: + - /bin/sh + - -c + - -e + args: + - | + {%- if DRYDOCK_MIGRATE_FROM == 13 %} + ./manage.py lms backpopulate_user_tours + {%- endif %} + {%- if DRYDOCK_MIGRATE_FROM in (13,14) %} + ./manage.py lms compute_grades -v1 --all_courses + {%- endif %} + env: + - name: SERVICE_VARIANT + value: lms + - name: DJANGO_SETTINGS_MODULE + value: lms.envs.tutor.production + volumeMounts: + - mountPath: /openedx/edx-platform/lms/envs/tutor/ + name: settings-lms + - mountPath: /openedx/edx-platform/cms/envs/tutor/ + name: settings-cms + - mountPath: /openedx/config + name: config + volumes: + - name: settings-lms + configMap: + name: openedx-settings-lms + - name: settings-cms + configMap: + name: openedx-settings-cms + - name: config + configMap: + name: openedx-config +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: drydock-upgrade-cms-job + labels: + drydock.io/component: job + drydock.io/target-service: cms + drydock.io/runner-service: cms + annotations: + argocd.argoproj.io/sync-wave: "{{ get_sync_waves_for_resource('drydock-upgrade-cms-job') }}" + argocd.argoproj.io/hook: Sync + argocd.argoproj.io/hook-delete-policy: HookSucceeded +spec: + ttlSecondsAfterFinished: 100 + template: + spec: + restartPolicy: Never + containers: + - name: cms + image: {{ DOCKER_IMAGE_OPENEDX }} + command: + - /bin/sh + - -c + - -e + args: + - | + {%- if DRYDOCK_MIGRATE_FROM == 13 %} + ./manage.py cms backfill_course_tabs + ./manage.py cms simulate_publish + {%- endif %} + env: + - name: SERVICE_VARIANT + value: cms + - name: DJANGO_SETTINGS_MODULE + value: cms.envs.tutor.production + volumeMounts: + - mountPath: /openedx/edx-platform/lms/envs/tutor/ + name: settings-lms + - mountPath: /openedx/edx-platform/cms/envs/tutor/ + name: settings-cms + - mountPath: /openedx/config + name: config + volumes: + - name: settings-lms + configMap: + name: openedx-settings-lms + - name: settings-cms + configMap: + name: openedx-settings-cms + - name: config + configMap: + name: openedx-config +{% endif %} diff --git a/drydock/templates/drydock/k8s/patches/hpa-sync-wave.yml b/drydock/templates/drydock/k8s/patches/hpa-sync-wave.yml new file mode 100644 index 00000000..5c4ef544 --- /dev/null +++ b/drydock/templates/drydock/k8s/patches/hpa-sync-wave.yml @@ -0,0 +1,8 @@ +apiVersion: not-used +kind: not-used +metadata: + name: not-used + annotations: + argocd.argoproj.io/sync-wave: "{{ get_sync_waves_for_resource('horizontalpodautoscalers:all') }}" + argocd.argoproj.io/hook: Sync + argocd.argoproj.io/hook-delete-policy: HookSucceeded diff --git a/drydock/templates/drydock/k8s/patches/post-init-deployments-sync-wave.yml b/drydock/templates/drydock/k8s/patches/post-init-deployments-sync-wave.yml new file mode 100644 index 00000000..5947dfae --- /dev/null +++ b/drydock/templates/drydock/k8s/patches/post-init-deployments-sync-wave.yml @@ -0,0 +1,6 @@ +apiVersion: not-used +kind: not-used +metadata: + name: not-used + annotations: + argocd.argoproj.io/sync-wave: "{{ get_sync_waves_for_resource('deployments:post-init-apps') }}" diff --git a/drydock/templates/drydock/k8s/patches/sync-wave-4.yml b/drydock/templates/drydock/k8s/patches/sync-wave-4.yml deleted file mode 100644 index dffb3fdd..00000000 --- a/drydock/templates/drydock/k8s/patches/sync-wave-4.yml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: not-used -kind: not-used -metadata: - name: not-used - annotations: - argocd.argoproj.io/sync-wave: "4" diff --git a/drydock/templates/drydock/k8s/patches/sync-wave-5.yml b/drydock/templates/drydock/k8s/patches/sync-wave-5.yml deleted file mode 100644 index c2471ee7..00000000 --- a/drydock/templates/drydock/k8s/patches/sync-wave-5.yml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: not-used -kind: not-used -metadata: - name: not-used - annotations: - argocd.argoproj.io/sync-wave: "5" diff --git a/drydock/templates/drydock/task/mongodb/init b/drydock/templates/drydock/task/mongodb/init new file mode 100644 index 00000000..fa603594 --- /dev/null +++ b/drydock/templates/drydock/task/mongodb/init @@ -0,0 +1,25 @@ +echo "Initialising MongoDB..." +mongo --host {{MONGODB_HOST }} {% if MONGODB_ROOT_USERNAME and MONGODB_ROOT_PASSWORD %} -u {{ MONGODB_ROOT_USERNAME }} -p {{ MONGODB_ROOT_PASSWORD }} {% endif %} admin <