diff --git a/tutormfe/patches/caddyfile b/tutormfe/patches/caddyfile index 55dec86f..feb8ed28 100644 --- a/tutormfe/patches/caddyfile +++ b/tutormfe/patches/caddyfile @@ -3,5 +3,6 @@ request_body { max_size 2MB } + reverse_proxy /api/mfe_config/v1* lms:8000 import proxy "mfe:8002" } diff --git a/tutormfe/patches/openedx-lms-development-settings b/tutormfe/patches/openedx-lms-development-settings index 19418256..c1d54aae 100644 --- a/tutormfe/patches/openedx-lms-development-settings +++ b/tutormfe/patches/openedx-lms-development-settings @@ -17,3 +17,28 @@ CORS_ORIGIN_WHITELIST.append("http://{{ MFE_HOST }}:{{ app["port"] }}") LOGIN_REDIRECT_WHITELIST.append("{{ MFE_HOST }}:{{ app["port"] }}") CSRF_TRUSTED_ORIGINS.append("{{ MFE_HOST }}:{{ app["port"] }}") {% endfor %} + +# Start of Dynamic config API settings + +ENABLE_MFE_CONFIG_API = True + +MFE_CONFIG = { + "BASE_URL": "{{ MFE_HOST }}", + "CREDENTIALS_BASE_URL": "/csrf/api/v1/token", + "DISCOVERY_API_BASE_URL": "{% if DISCOVERY_HOST is defined %}http://{{ DISCOVERY_HOST }}:8381{% endif %}", + "FAVICON_URL": "http://{{ LMS_HOST }}/favicon.ico", + "LANGUAGE_PREFERENCE_COOKIE_NAME": "openedx-language-preference", + "LMS_BASE_URL": "http://{{ LMS_HOST }}:8000", + "LOGIN_URL": "http://{{ LMS_HOST }}:8000/login", + "LOGO_URL": "http://{{ LMS_HOST }}:8000/theming/asset/images/logo.png", + "LOGO_TRADEMARK_URL": "http://{{ LMS_HOST }}:8000/theming/asset/images/logo.png", + "LOGOUT_URL": "http://{{ LMS_HOST }}:8000/logout", + "MARKETING_SITE_BASE_URL": "http://{{ LMS_HOST }}:8000", + "REFRESH_ACCESS_TOKEN_ENDPOINT": "http://{{ LMS_HOST }}:8000/login_refresh", + "SITE_NAME": "{{ PLATFORM_NAME }}", + "STUDIO_BASE_URL": "http://{{ CMS_HOST }}:8001", + "USER_INFO_COOKIE_NAME": "user-info", + "ACCESS_TOKEN_COOKIE_NAME": "edx-jwt-cookie-header-payload", +} + +# Ends Dynamic config API settings diff --git a/tutormfe/patches/openedx-lms-production-settings b/tutormfe/patches/openedx-lms-production-settings index f69bf0d1..432eec1c 100644 --- a/tutormfe/patches/openedx-lms-production-settings +++ b/tutormfe/patches/openedx-lms-production-settings @@ -14,3 +14,31 @@ PROFILE_MICROFRONTEND_URL = "{% if ENABLE_HTTPS %}https://{% else %}http://{% en LOGIN_REDIRECT_WHITELIST.append("{{ MFE_HOST }}") CORS_ORIGIN_WHITELIST.append("{% if ENABLE_HTTPS %}https://{% else %}http://{% endif %}{{ MFE_HOST }}") CSRF_TRUSTED_ORIGINS.append("{{ MFE_HOST }}") + +ALLOWED_HOSTS.append("{{ MFE_HOST }}") + +# Start of Dynamic config API settings + +ENABLE_MFE_CONFIG_API = True + +MFE_CONFIG = { + "BASE_URL": "{{ MFE_HOST }}", + "CREDENTIALS_BASE_URL": "/csrf/api/v1/token", + "DISCOVERY_API_BASE_URL": "{% if DISCOVERY_HOST is defined %}{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ DISCOVERY_HOST }}{% endif %}", + "FAVICON_URL": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/favicon.ico", + "LANGUAGE_PREFERENCE_COOKIE_NAME": "openedx-language-preference", + "LMS_BASE_URL": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}", + "LOGIN_URL": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/login", + "LOGO_URL": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/theming/asset/images/logo.png", + "LOGO_TRADEMARK_URL": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/theming/asset/images/logo.png", + "LOGOUT_URL": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/logout", + "MARKETING_SITE_BASE_URL": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}", + "REFRESH_ACCESS_TOKEN_ENDPOINT": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/login_refresh", + "SITE_NAME": "{{ PLATFORM_NAME }}", + "STUDIO_BASE_URL": "{{ "https" if ENABLE_HTTPS else "http" }}://{{ CMS_HOST }}", + "USER_INFO_COOKIE_NAME": "user-info", + "ACCESS_TOKEN_COOKIE_NAME": "edx-jwt-cookie-header-payload", +} + + +# Ends Dynamic config API settings diff --git a/tutormfe/plugin.py b/tutormfe/plugin.py index 84c014cd..ecf974a2 100644 --- a/tutormfe/plugin.py +++ b/tutormfe/plugin.py @@ -3,6 +3,7 @@ import pkg_resources from tutor import hooks as tutor_hooks +from tutor.hooks import priorities from .__about__ import __version__ @@ -15,34 +16,23 @@ "CADDY_DOCKER_IMAGE": "{{ DOCKER_IMAGE_CADDY }}", "ACCOUNT_MFE_APP": { "name": "account", - "repository": "https://github.com/edx/frontend-app-account", + "repository": "https://github.com/openedx/frontend-app-account", "port": 1997, - "env": { - "production": { - "COACHING_ENABLED": "", - "ENABLE_DEMOGRAPHICS_COLLECTION": "", - }, - }, }, "GRADEBOOK_MFE_APP": { "name": "gradebook", - "repository": "https://github.com/edx/frontend-app-gradebook", + "repository": "https://github.com/openedx/frontend-app-gradebook", "port": 1994, }, "LEARNING_MFE_APP": { "name": "learning", - "repository": "https://github.com/edx/frontend-app-learning", + "repository": "https://github.com/openedx/frontend-app-learning", "port": 2000, }, "PROFILE_MFE_APP": { "name": "profile", - "repository": "https://github.com/edx/frontend-app-profile", + "repository": "https://github.com/openedx/frontend-app-profile", "port": 1995, - "env": { - "production": { - "ENABLE_LEARNER_RECORD_MFE": "true", - }, - }, }, }, } @@ -62,6 +52,15 @@ ) ) +tutor_hooks.Filters.IMAGES_PULL.add_item(( + "mfe", + "{{ MFE_DOCKER_IMAGE }}", +)) +tutor_hooks.Filters.IMAGES_PUSH.add_item(( + "mfe", + "{{ MFE_DOCKER_IMAGE }}", +)) + @tutor_hooks.Filters.COMPOSE_MOUNTS.add() def _mount_frontend_apps(volumes, name): @@ -82,27 +81,7 @@ def _mount_frontend_apps(volumes, name): return volumes -@tutor_hooks.Filters.IMAGES_PULL.add() -@tutor_hooks.Filters.IMAGES_PUSH.add() -def _add_remote_mfe_image_iff_customized(images, user_config): - """ - Register MFE image for pushing & pulling if and only if it has - been set to something other than the default. - - This is work-around to an upstream issue with MFE config. Briefly: - User config is baked into MFE builds, so Tutor cannot host a generic - pre-built MFE image. Howevever, individual Tutor users may want/need to - build and host their own MFE image. So, as a compromise, we tell Tutor - to push/pull the MFE image if the user has customized it to anything - other than the default image URL. - """ - image_tag = user_config["MFE_DOCKER_IMAGE"] - if not image_tag.startswith("docker.io/overhangio/openedx-mfe:"): - # Image has been customized. Add to list for pulling/pushing. - images.append(("mfe", image_tag)) - return images - -####### Boilerplate code +# Boilerplate code # Add the "templates" folder as a template root tutor_hooks.Filters.ENV_TEMPLATE_ROOTS.add_item( pkg_resources.resource_filename("tutormfe", "templates") @@ -122,7 +101,13 @@ def _add_remote_mfe_image_iff_customized(images, user_config): ) ): with open(path, encoding="utf-8") as patch_file: - tutor_hooks.Filters.ENV_PATCHES.add_item((os.path.basename(path), patch_file.read())) + # Here we force tutor-mfe lms patches to be loaded first, thus ensuring when opreators override + # MFE_CONFIG and/or MFE_CONFIG_OVERRIDES, their patches will be loaded after this plugin's + patch_name = os.path.basename(path) + priority = priorities.HIGH if patch_name in \ + ['openedx-lms-production-settings', 'openedx-lms-development-settings'] \ + else priorities.DEFAULT + tutor_hooks.Filters.ENV_PATCHES.add_item((patch_name, patch_file.read()), priority=priority) # Add configuration entries tutor_hooks.Filters.CONFIG_DEFAULTS.add_items( diff --git a/tutormfe/templates/mfe/apps/mfe/webpack.dev-tutor.config.js b/tutormfe/templates/mfe/apps/mfe/webpack.dev-tutor.config.js index 3a7df6e2..ee7f9ccb 100644 --- a/tutormfe/templates/mfe/apps/mfe/webpack.dev-tutor.config.js +++ b/tutormfe/templates/mfe/apps/mfe/webpack.dev-tutor.config.js @@ -14,6 +14,9 @@ module.exports = merge(baseDevConfig, { // We will have to make changes to thix config in later releases of webpack dev devServer // https://github.com/webpack/webpack-dev-server/blob/master/migration-v4.md allowedHosts: 'all', + proxy: { + '/api/mfe_config/v1' : 'http://{{ LMS_HOST }}:8000', + } }, }) diff --git a/tutormfe/templates/mfe/build/mfe/Dockerfile b/tutormfe/templates/mfe/build/mfe/Dockerfile index e10ec150..597a8a8b 100644 --- a/tutormfe/templates/mfe/build/mfe/Dockerfile +++ b/tutormfe/templates/mfe/build/mfe/Dockerfile @@ -51,43 +51,26 @@ RUN npm clean-install --no-audit --no-fund --registry=$NPM_REGISTRY \ {{ patch("mfe-dockerfile-post-npm-install") }} COPY --from={{ app["name"] }}-src /openedx/app /openedx/app COPY --from={{ app["name"] }}-i18n /openedx/app/src/i18n/messages /openedx/app/src/i18n/messages -ENV PUBLIC_PATH='/{{ app["name"] }}/' EXPOSE {{ app['port'] }} -COPY ./env/production /openedx/env/production -{%- set overrides = app.get("env", {}).get("production", {}) %} -{%- if overrides %} -RUN echo "setting production overrides..." \ - {%- for key, value in app.get("env", {}).get("production", {}).items() %} - && echo "{{ key }}='{{ value }}'" >> /openedx/env/production \ - {%- endfor %} - && echo "done setting production overrides" -{%- endif %} +# configuration needed at build time +ENV APP_ID={{ app["name"] }} +ENV PUBLIC_PATH='/{{ app["name"] }}/' +ENV MFE_CONFIG_API_URL=/api/mfe_config/v1 +ARG ENABLE_NEW_RELIC=false ######## {{ app["name"] }} (dev) FROM {{ app["name"] }}-common AS {{ app["name"] }}-dev -COPY ./env/development /openedx/env/development -{%- set overrides = app.get("env", {}).get("development", {}) %} -{%- if overrides %} -RUN echo "setting development overrides..." \ - {%- for key, value in overrides.items() %} - && echo "{{ key }}='{{ value }}'" >> /openedx/env/development \ - {%- endfor %} - && echo "done setting development overrides" -{%- endif %} -CMD ["/bin/bash", "-c", "set -a && \ - source /openedx/env/production && \ - source /openedx/env/development && \ - npm run start --- --config ./webpack.dev-tutor.config.js"] +ENV NODE_ENV=development +CMD ["/bin/bash", "-c", "npm run start --- --config ./webpack.dev-tutor.config.js"] {% endfor %} # Production images are last to accelerate dev image building {%- for app in iter_values_named(suffix="MFE_APP") %} ######## {{ app["name"] }} (production) FROM {{ app["name"] }}-common AS {{ app["name"] }}-prod -RUN bash -c "set -a && \ - source /openedx/env/production && \ - npm run build" +ENV NODE_ENV=production +RUN npm run build {% endfor %} ####### final production image with all static assets diff --git a/tutormfe/templates/mfe/build/mfe/env/development b/tutormfe/templates/mfe/build/mfe/env/development deleted file mode 100644 index d0d4f9eb..00000000 --- a/tutormfe/templates/mfe/build/mfe/env/development +++ /dev/null @@ -1,12 +0,0 @@ -DISCOVERY_API_BASE_URL={% if DISCOVERY_HOST is defined %}http://{{ DISCOVERY_HOST }}:8381{% endif %} -LMS_BASE_URL=http://{{ LMS_HOST }}:8000 -LOGIN_URL=http://{{ LMS_HOST }}:8000/login -LOGO_URL=http://{{ LMS_HOST }}:8000/theming/asset/images/logo.png -LOGO_TRADEMARK_URL=http://{{ LMS_HOST }}:8000/theming/asset/images/logo.png -LOGOUT_URL=http://{{ LMS_HOST }}:8000/logout -MARKETING_SITE_BASE_URL=http://{{ LMS_HOST }}:8000 -NODE_ENV=development -REFRESH_ACCESS_TOKEN_ENDPOINT=http://{{ LMS_HOST }}:8000/login_refresh -STUDIO_BASE_URL=http://{{ CMS_HOST }}:8001 - -{{ patch("mfe-env-development") }} diff --git a/tutormfe/templates/mfe/build/mfe/env/production b/tutormfe/templates/mfe/build/mfe/env/production deleted file mode 100644 index cf224b51..00000000 --- a/tutormfe/templates/mfe/build/mfe/env/production +++ /dev/null @@ -1,26 +0,0 @@ -{# https://edx.readthedocs.io/projects/edx-developer-docs/en/latest/micro_frontends/index.html#required-environment-variables #} -ACCESS_TOKEN_COOKIE_NAME=edx-jwt-cookie-header-payload -BASE_URL={{ MFE_HOST }} -CSRF_TOKEN_API_PATH=/csrf/api/v1/token -CREDENTIALS_BASE_URL= -DISCOVERY_API_BASE_URL={% if DISCOVERY_HOST is defined %}{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ DISCOVERY_HOST }}{% endif %} -ECOMMERCE_BASE_URL= -ENABLE_NEW_RELIC=false -FAVICON_URL={% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/favicon.ico -LANGUAGE_PREFERENCE_COOKIE_NAME=openedx-language-preference -LMS_BASE_URL={% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }} -LOGIN_URL={% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/login -LOGO_URL={% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/theming/asset/images/logo.png -LOGO_TRADEMARK_URL={% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/theming/asset/images/logo.png -LOGO_WHITE_URL= -LOGOUT_URL={% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/logout -MARKETING_SITE_BASE_URL={% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }} -NODE_ENV=production -PUBLISHER_BASE_URL= -REFRESH_ACCESS_TOKEN_ENDPOINT={% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/login_refresh -SEGMENT_KEY= -SITE_NAME="{{ PLATFORM_NAME }}" -STUDIO_BASE_URL={{ "https" if ENABLE_HTTPS else "http" }}://{{ CMS_HOST }} -USER_INFO_COOKIE_NAME=user-info - -{{ patch("mfe-env-production") }}