From 29ed3d911a8988bafb7c37daaa755678920aaa6a Mon Sep 17 00:00:00 2001 From: Kyle McCormick Date: Mon, 10 Jan 2022 11:20:10 -0500 Subject: [PATCH] build: expose working openedx/lms and openedx/cms docker images (#29549) This commits prepares edx-platform's experimental Dockerfile for optional use in devstack. Presently, the image built by this Dockerfile isn't used anywhere. Notable changes: * Drop the openedx/edx-platform image name in favor of openedx/lms and openedx/cms. * Drop the newrelic stages and tags. * Create openedx/lms-dev and openedx/cms-dev image variants which use Django devserver, install dev requirements, and specify devstack Django settings. * Add config files at (lms,cms)/envs/devstack-experimental.yml, extracted from the existing edxapp docker image. * Adds three new scripts, each of which replaces an Ansible or Paver-supported function with a pure bash + Django management command implementation. --- .dockerignore | 2 + Dockerfile | 245 +++++++---- Makefile | 25 +- cms/envs/devstack-experimental.yml | 523 ++++++++++++++++++++++++ lms/envs/devstack-experimental.yml | 626 +++++++++++++++++++++++++++++ scripts/provision-demo-course.sh | 31 ++ scripts/provision-demo-users.sh | 47 +++ scripts/update-assets-dev.sh | 92 +++++ 8 files changed, 1502 insertions(+), 89 deletions(-) create mode 100644 cms/envs/devstack-experimental.yml create mode 100644 lms/envs/devstack-experimental.yml create mode 100755 scripts/provision-demo-course.sh create mode 100755 scripts/provision-demo-users.sh create mode 100755 scripts/update-assets-dev.sh diff --git a/.dockerignore b/.dockerignore index 496a05a3ac..64eecf5ed7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -149,3 +149,5 @@ openedx/core/djangoapps/django_comment_common/comment_client/python # Locally generated PII reports **/pii_report + +/Dockerfile diff --git a/Dockerfile b/Dockerfile index c2c3c96764..c21e599736 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,108 +1,193 @@ FROM ubuntu:focal as base # Warning: This file is experimental. - -# Install system requirements +# +# Short-term goals: +# * Be a suitable replacement for the `edxops/edxapp` image in devstack (in progress). +# * Take advantage of Docker caching layers: aim to put commands in order of +# increasing cache-busting frequency. +# * Related to ^, use no Ansible or Paver. +# Long-term goal: +# * Be a suitable base for production LMS and CMS images (THIS IS NOT YET THE CASE!). +# +# Install system requirements. +# We update, upgrade, and delete lists all in one layer +# in order to reduce total image size. RUN apt-get update && \ - # Global requirements DEBIAN_FRONTEND=noninteractive apt-get install --yes \ - build-essential \ - curl \ - # If we don't need gcc, we should remove it. - g++ \ - gcc \ - git \ - git-core \ - language-pack-en \ - libfreetype6-dev \ - libmysqlclient-dev \ - libssl-dev \ - libxml2-dev \ - libxmlsec1-dev \ - libxslt1-dev \ - swig \ - # openedx requirements - gettext \ - gfortran \ - graphviz \ - libffi-dev \ - libfreetype6-dev \ - libgeos-dev \ - libgraphviz-dev \ - libjpeg8-dev \ - liblapack-dev \ - libpng-dev \ - libsqlite3-dev \ - libxml2-dev \ - libxmlsec1-dev \ - libxslt1-dev \ - # lynx: Required by https://github.com/edx/edx-platform/blob/b489a4ecb122/openedx/core/lib/html_to_text.py#L16 - lynx \ - ntp \ - pkg-config \ - python3-dev \ - python3-venv \ - && rm -rf /var/lib/apt/lists/* + # Global requirements + build-essential \ + curl \ + # If we don't need gcc, we should remove it. + g++ \ + gcc \ + git \ + git-core \ + language-pack-en \ + libfreetype6-dev \ + libmysqlclient-dev \ + libssl-dev \ + libxml2-dev \ + libxmlsec1-dev \ + libxslt1-dev \ + swig \ + # openedx requirements + gettext \ + gfortran \ + graphviz \ + libffi-dev \ + libfreetype6-dev \ + libgeos-dev \ + libgraphviz-dev \ + libjpeg8-dev \ + liblapack-dev \ + libpng-dev \ + libsqlite3-dev \ + libxml2-dev \ + libxmlsec1-dev \ + libxslt1-dev \ + # lynx: Required by https://github.com/edx/edx-platform/blob/b489a4ecb122/openedx/core/lib/html_to_text.py#L16 + lynx \ + ntp \ + pkg-config \ + python3-dev \ + python3-venv && \ + rm -rf /var/lib/apt/lists/* +# Set locale. RUN locale-gen en_US.UTF-8 -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 +# Env vars: locale +ENV LANG='en_US.UTF-8' +ENV LANGUAGE='en_US:en' +ENV LC_ALL='en_US.UTF-8' + +# Env vars: configuration +ENV CONFIG_ROOT='/edx/etc' +ENV LMS_CFG="$CONFIG_ROOT/lms.yml" +ENV CMS_CFG="$CONFIG_ROOT/cms.yml" +ENV EDX_PLATFORM_SETTINGS='production' + +# Env vars: path +ENV VIRTUAL_ENV='/edx/app/edxapp/venvs/edxapp' +ENV PATH="$VIRTUAL_ENV/bin:$PATH" +ENV PATH="/edx/app/edxapp/edx-platform/node_modules/.bin:${PATH}" +ENV PATH="/edx/app/edxapp/edx-platform/bin:${PATH}" +ENV PATH="/edx/app/edxapp/nodeenv/bin:${PATH}" + +# Create config directory. Create, define, and switch to working directory. +RUN mkdir -p "$CONFIG_ROOT" WORKDIR /edx/app/edxapp/edx-platform -ENV PATH /edx/app/edxapp/nodeenv/bin:${PATH} -ENV PATH ./node_modules/.bin:${PATH} -ENV CONFIG_ROOT /edx/etc/ -ENV PATH /edx/app/edxapp/edx-platform/bin:${PATH} -ENV SETTINGS production -RUN mkdir -p /edx/etc/ +# Env vars: paver +# We intentionally don't use paver in this Dockerfile, but Devstack may invoke paver commands +# during provisioning. Enabling NO_PREREQ_INSTALL tells paver not to re-install Python +# requirements for every paver command, potentially saving a lot of developer time. +ENV NO_PREREQ_INSTALL='1' -ENV VIRTUAL_ENV=/edx/app/edxapp/venvs/edxapp -RUN python3.8 -m venv $VIRTUAL_ENV -ENV PATH="$VIRTUAL_ENV/bin:$PATH" +# Set up a Python virtual environment. +# It is already 'activated' because $VIRTUAL_ENV/bin was put on $PATH. +RUN python3.8 -m venv "$VIRTUAL_ENV" -# Install Python requirements -COPY setup.py setup.py -COPY common common -COPY openedx openedx -COPY lms lms -COPY cms cms -COPY requirements/pip.txt requirements/pip.txt -COPY requirements/edx/base.txt requirements/edx/base.txt +# Install Python requirements. +# Requires copying over requirements files, but not entire repository. +# We filter out the local ('common/*' and 'openedx/*', and '.') Python projects, +# because those require code in order to be installed. They will be installed +# later. This step can be simplified when the local projects are dissolved +# (see https://openedx.atlassian.net/browse/BOM-2579). +COPY requirements requirements +RUN sed '/^-e \(common\/\|openedx\/\|.\)/d' requirements/edx/base.txt \ + > requirements/edx/base-minus-local.txt RUN pip install -r requirements/pip.txt -RUN pip install -r requirements/edx/base.txt +RUN pip install -r requirements/edx/base-minus-local.txt -# Copy just JS requirements and install them. +# Set up a Node environment and install Node requirements. +# Must be done after Python requirements, since nodeenv is installed +# via pip. +# The node environment is already 'activated' because its .../bin was put on $PATH. +RUN nodeenv /edx/app/edxapp/nodeenv --node=12.11.1 --prebuilt COPY package.json package.json COPY package-lock.json package-lock.json -RUN nodeenv /edx/app/edxapp/nodeenv --node=12.11.1 --prebuilt RUN npm set progress=false && npm install -ENV LMS_CFG /edx/etc/lms.yml -ENV STUDIO_CFG /edx/etc/studio.yml - -# Copy over remaining code. -# We do this as late as possible so that small changes to the repo don't bust -# the requirements cache. +# Copy over remaining parts of repository (including all code). COPY . . +# Install Python requirements again in order to capture local projects, which +# were skipped earlier. This should be much quicker than if were installing +# all requirements from scratch. +RUN pip install -r requirements/edx/base.txt + + +################################################## +# Define LMS non-dev target. FROM base as lms ENV SERVICE_VARIANT lms -ENV DJANGO_SETTINGS_MODULE lms.envs.production +ENV DJANGO_SETTINGS_MODULE="lms.envs.$EDX_PLATFORM_SETTINGS" EXPOSE 8000 -CMD gunicorn -c /edx/app/edxapp/edx-platform/lms/docker_lms_gunicorn.py --name lms --bind=0.0.0.0:8000 --max-requests=1000 --access-logfile - lms.wsgi:application +CMD gunicorn \ + -c /edx/app/edxapp/edx-platform/lms/docker_lms_gunicorn.py \ + --name lms \ + --bind=0.0.0.0:8000 \ + --max-requests=1000 \ + --access-logfile \ + - lms.wsgi:application -FROM lms as lms-newrelic -RUN pip install newrelic -CMD newrelic-admin run-program gunicorn -c /edx/app/edxapp/edx-platform/lms/docker_lms_gunicorn.py --name lms --bind=0.0.0.0:8000 --max-requests=1000 --access-logfile - lms.wsgi:application -FROM base as studio +################################################## +# Define CMS non-dev target. +FROM base as cms ENV SERVICE_VARIANT cms -ENV DJANGO_SETTINGS_MODULE cms.envs.production +ENV EDX_PLATFORM_SETTINGS='production' +ENV DJANGO_SETTINGS_MODULE="cms.envs.$EDX_PLATFORM_SETTINGS" EXPOSE 8010 -CMD gunicorn -c /edx/app/edxapp/edx-platform/cms/docker_cms_gunicorn.py --name cms --bind=0.0.0.0:8010 --max-requests=1000 --access-logfile - cms.wsgi:application +CMD gunicorn \ + -c /edx/app/edxapp/edx-platform/cms/docker_cms_gunicorn.py \ + --name cms \ + --bind=0.0.0.0:8010 \ + --max-requests=1000 \ + --access-logfile \ + - cms.wsgi:application -FROM studio as studio-newrelic -RUN pip install newrelic -CMD newrelic-admin run-program gunicorn -c /edx/app/edxapp/edx-platform/cms/docker_cms_gunicorn.py --name cms --bind=0.0.0.0:8010 --max-requests=1000 --access-logfile - cms.wsgi:application + +################################################## +# Define intermediate dev target for LMS/CMS. +# +# Although it might seem more logical to forego the `dev` stage +# and instead base `lms-dev` and `cms-dev` off of `lms` and +# `cms`, respectively, we choose to have this `dev` stage +# so that the installed development requirements are contained +# in a single layer, shared between `lms-dev` and `cms-dev`. +FROM base as dev +RUN pip install -r requirements/edx/development.txt + +# Link configuration YAMLs and set EDX_PLATFORM_SE1TTINGS. +ENV EDX_PLATFORM_SETTINGS='devstack_docker' +RUN ln -s "$(pwd)/lms/envs/devstack-experimental.yml" "$LMS_CFG" +RUN ln -s "$(pwd)/cms/envs/devstack-experimental.yml" "$CMS_CFG" + +# Temporary compatibility hack while devstack is supporting +# both the old `edxops/edxapp` image and this image: +# Add in a dummy ../edxapp_env file. +# The edxapp_env file was originally needed for sourcing to get +# environment variables like LMS_CFG, but now we just set +# those variables right in the Dockerfile. +RUN touch ../edxapp_env + + +################################################## +# Define LMS dev target. +FROM dev as lms-dev +ENV SERVICE_VARIANT lms +ENV DJANGO_SETTINGS_MODULE="lms.envs.$EDX_PLATFORM_SETTINGS" +EXPOSE 18000 +CMD while true; do python ./manage.py lms runserver 0.0.0.0:18000; sleep 2; done + + +################################################## +# Define CMS dev target. +FROM dev as cms-dev +ENV SERVICE_VARIANT cms +ENV DJANGO_SETTINGS_MODULE="cms.envs.$EDX_PLATFORM_SETTINGS" +EXPOSE 18010 +CMD while true; do python ./manage.py cms runserver 0.0.0.0:18010; sleep 2; done diff --git a/Makefile b/Makefile index 75446df396..d411da9e74 100644 --- a/Makefile +++ b/Makefile @@ -129,20 +129,27 @@ upgrade: pre-requirements ## update the pip requirements files to use the lates check-types: ## run static type-checking tests mypy -# These make targets currently only build LMS images. docker_build: - docker build . -f Dockerfile --target lms -t openedx/edx-platform - docker build . -f Dockerfile --target lms-newrelic -t openedx/edx-platform:latest-newrelic + docker build . -f Dockerfile --target lms -t openedx/lms + docker build . -f Dockerfile --target lms-dev -t openedx/lms-dev + docker build . -f Dockerfile --target cms -t openedx/cms + docker build . -f Dockerfile --target cms-dev -t openedx/cms-dev docker_tag: docker_build - docker tag openedx/edx-platform openedx/edx-platform:${GITHUB_SHA} - docker tag openedx/edx-platform:latest-newrelic openedx/edx-platform:${GITHUB_SHA}-newrelic + docker tag openedx/lms openedx/lms:${GITHUB_SHA} + docker tag openedx/lms-dev openedx/lms-dev:${GITHUB_SHA} + docker tag openedx/cms openedx/cms:${GITHUB_SHA} + docker tag openedx/cms-dev openedx/cms-dev:${GITHUB_SHA} docker_auth: echo "$$DOCKERHUB_PASSWORD" | docker login -u "$$DOCKERHUB_USERNAME" --password-stdin docker_push: docker_tag docker_auth ## push to docker hub - docker push 'openedx/edx-platform:latest' - docker push "openedx/edx-platform:${GITHUB_SHA}" - docker push 'openedx/edx-platform:latest-newrelic' - docker push "openedx/edx-platform:${GITHUB_SHA}-newrelic" + docker push "openedx/lms:latest" + docker push "openedx/lms:${GITHUB_SHA}" + docker push "openedx/lms-dev:latest" + docker push "openedx/lms-dev:${GITHUB_SHA}" + docker push "openedx/cms:latest" + docker push "openedx/cms:${GITHUB_SHA}" + docker push "openedx/cms-dev:latest" + docker push "openedx/cms-dev:${GITHUB_SHA}" diff --git a/cms/envs/devstack-experimental.yml b/cms/envs/devstack-experimental.yml new file mode 100644 index 0000000000..81619af2dc --- /dev/null +++ b/cms/envs/devstack-experimental.yml @@ -0,0 +1,523 @@ +# This file is an experimental extraction of /edx/etc/studio.yml from +# a CMS devstack container. +# +# When devstack is configured to use the new `openedx/` images +# instead of the old `edxops/edxapp` image, it will use this file +# as input to cms/envs/production.py (and, in turn, cms/envs/devstack.py). +# If you are using devstack with the `edxops/edxapp` image, though, +# this file is NOT used. +# +# Q. Should I update this file when I update devstack.py? +# A. You don't *have* to, because settings in devstack.py +# override these settings. But, it doesn't harm to also make them +# here in order to quell confusion. The hope is that we'll +# adpot OEP-45 eventually, which recommends against having +# a devstack.py at all. +# +# This is part of the effort to move our dev tools off of Ansible and +# Paver, described here: https://github.com/edx/devstack/pull/866 +# TODO: If the effort described above is abandoned, then this file should +# probably be deleted. +ACTIVATION_EMAIL_SUPPORT_LINK: '' +AFFILIATE_COOKIE_NAME: dev_affiliate_id +ALTERNATE_WORKER_QUEUES: lms +ANALYTICS_DASHBOARD_NAME: Your Platform Name Here Insights +ANALYTICS_DASHBOARD_URL: http://localhost:18110/courses +AUTH_PASSWORD_VALIDATORS: +- NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator +- NAME: common.djangoapps.util.password_policy_validators.MinimumLengthValidator + OPTIONS: + min_length: 2 +- NAME: common.djangoapps.util.password_policy_validators.MaximumLengthValidator + OPTIONS: + max_length: 75 +AWS_ACCESS_KEY_ID: null +AWS_QUERYSTRING_AUTH: false +AWS_S3_CUSTOM_DOMAIN: SET-ME-PLEASE (ex. bucket-name.s3.amazonaws.com) +AWS_SECRET_ACCESS_KEY: null +AWS_SES_REGION_ENDPOINT: email.us-east-1.amazonaws.com +AWS_SES_REGION_NAME: us-east-1 +AWS_STORAGE_BUCKET_NAME: SET-ME-PLEASE (ex. bucket-name) +BASE_COOKIE_DOMAIN: localhost +BLOCKSTORE_API_URL: http://localhost:18250/api/v1 +BLOCKSTORE_PUBLIC_URL_ROOT: http://localhost:18250 +BLOCK_STRUCTURES_SETTINGS: + COURSE_PUBLISH_TASK_DELAY: 30 + PRUNING_ACTIVE: false + TASK_DEFAULT_RETRY_DELAY: 30 + TASK_MAX_RETRIES: 5 +BRANCH_IO_KEY: '' +BUGS_EMAIL: bugs@example.com +BULK_EMAIL_DEFAULT_FROM_EMAIL: no-reply@example.com +BULK_EMAIL_EMAILS_PER_TASK: 500 +BULK_EMAIL_LOG_SENT_EMAILS: false +CACHES: + celery: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: celery + LOCATION: + - edx.devstack.memcached:11211 + TIMEOUT: '7200' + configuration: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: 78f87108afce + LOCATION: + - edx.devstack.memcached:11211 + course_structure_cache: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: course_structure + LOCATION: + - edx.devstack.memcached:11211 + TIMEOUT: '7200' + default: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: default + LOCATION: + - edx.devstack.memcached:11211 + VERSION: '1' + general: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: general + LOCATION: + - edx.devstack.memcached:11211 + mongo_metadata_inheritance: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: mongo_metadata_inheritance + LOCATION: + - edx.devstack.memcached:11211 + TIMEOUT: 300 + staticfiles: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: 78f87108afce_general + LOCATION: + - edx.devstack.memcached:11211 +CAS_ATTRIBUTE_CALLBACK: '' +CAS_EXTRA_LOGIN_PARAMS: '' +CAS_SERVER_URL: '' +CELERYBEAT_SCHEDULER: celery.beat:PersistentScheduler +CELERY_BROKER_HOSTNAME: localhost +CELERY_BROKER_PASSWORD: '' +CELERY_BROKER_TRANSPORT: redis +CELERY_BROKER_USER: '' +CELERY_BROKER_USE_SSL: false +CELERY_BROKER_VHOST: '' +CELERY_EVENT_QUEUE_TTL: null +CELERY_QUEUES: +- edx.cms.core.default +- edx.cms.core.high +CELERY_TIMEZONE: UTC +CERTIFICATE_TEMPLATE_LANGUAGES: + en: English + es: Español +CERT_QUEUE: certificates +CMS_BASE: edx.devstack.studio:18010 +CODE_JAIL: + limits: + CPU: 1 + FSIZE: 1048576 + PROXY: 0 + REALTIME: 3 + VMEM: 536870912 + python_bin: /edx/app/edxapp/venvs/edxapp-sandbox/bin/python + user: sandbox +COMMENTS_SERVICE_KEY: password +COMMENTS_SERVICE_URL: http://localhost:18080 +COMPREHENSIVE_THEME_DIRS: +- '' +COMPREHENSIVE_THEME_LOCALE_PATHS: [] +CONTACT_EMAIL: info@example.com +CONTENTSTORE: + ADDITIONAL_OPTIONS: {} + DOC_STORE_CONFIG: + authsource: '' + collection: modulestore + connectTimeoutMS: 2000 + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + read_preference: PRIMARY + replicaSet: '' + socketTimeoutMS: 3000 + ssl: false + user: edxapp + ENGINE: xmodule.contentstore.mongo.MongoContentStore + OPTIONS: + auth_source: '' + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + ssl: false + user: edxapp +CORS_ORIGIN_ALLOW_ALL: false +CORS_ORIGIN_WHITELIST: [] +COURSES_WITH_UNSAFE_CODE: [] +COURSE_ABOUT_VISIBILITY_PERMISSION: see_exists +COURSE_AUTHORING_MICROFRONTEND_URL: null +COURSE_CATALOG_API_URL: http://localhost:8008/api/v1 +COURSE_CATALOG_URL_ROOT: http://localhost:8008 +COURSE_CATALOG_VISIBILITY_PERMISSION: see_exists +COURSE_IMPORT_EXPORT_BUCKET: '' +CREDENTIALS_INTERNAL_SERVICE_URL: http://localhost:8005 +CREDENTIALS_PUBLIC_SERVICE_URL: http://localhost:8005 +CREDIT_PROVIDER_SECRET_KEYS: {} +CROSS_DOMAIN_CSRF_COOKIE_DOMAIN: '' +CROSS_DOMAIN_CSRF_COOKIE_NAME: '' +CSRF_COOKIE_SECURE: false +CSRF_TRUSTED_ORIGINS: [] +DASHBOARD_COURSE_LIMIT: null +DATABASES: + default: + ATOMIC_REQUESTS: true + CONN_MAX_AGE: 0 + ENGINE: django.db.backends.mysql + HOST: edx.devstack.mysql57 + NAME: edxapp + OPTIONS: + isolation_level: read committed + PASSWORD: password + PORT: '3306' + USER: edxapp001 + read_replica: + CONN_MAX_AGE: 0 + ENGINE: django.db.backends.mysql + HOST: edx.devstack.mysql57 + NAME: edxapp + OPTIONS: + isolation_level: read committed + PASSWORD: password + PORT: '3306' + USER: edxapp001 + student_module_history: + CONN_MAX_AGE: 0 + ENGINE: django.db.backends.mysql + HOST: edx.devstack.mysql57 + NAME: edxapp_csmh + OPTIONS: + isolation_level: read committed + PASSWORD: password + PORT: '3306' + USER: edxapp001 +DATA_DIR: /edx/var/edxapp +DEFAULT_COURSE_VISIBILITY_IN_CATALOG: both +DEFAULT_FEEDBACK_EMAIL: feedback@example.com +DEFAULT_FILE_STORAGE: django.core.files.storage.FileSystemStorage +DEFAULT_FROM_EMAIL: registration@example.com +DEFAULT_JWT_ISSUER: + AUDIENCE: lms-key + ISSUER: http://edx.devstack.lms:18000/oauth2 + SECRET_KEY: lms-secret +DEFAULT_MOBILE_AVAILABLE: false +DEFAULT_SITE_THEME: '' +DEPRECATED_ADVANCED_COMPONENT_TYPES: [] +DJFS: + directory_root: /edx/var/edxapp/django-pyfs/static/django-pyfs + type: osfs + url_root: /static/django-pyfs +DOC_STORE_CONFIG: + authsource: '' + collection: modulestore + connectTimeoutMS: 2000 + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + read_preference: PRIMARY + replicaSet: '' + socketTimeoutMS: 3000 + ssl: false + user: edxapp +ECOMMERCE_API_SIGNING_KEY: lms-secret +ECOMMERCE_API_URL: http://localhost:8002/api/v2 +ECOMMERCE_PUBLIC_URL_ROOT: http://localhost:8002 +EDXMKTG_USER_INFO_COOKIE_NAME: edx-user-info +EDX_PLATFORM_REVISION: master +ELASTIC_SEARCH_CONFIG: +- host: edx.devstack.elasticsearch + port: 9200 + use_ssl: false +EMAIL_BACKEND: django.core.mail.backends.smtp.EmailBackend +EMAIL_HOST: localhost +EMAIL_HOST_PASSWORD: '' +EMAIL_HOST_USER: '' +EMAIL_PORT: 25 +EMAIL_USE_TLS: false +ENABLE_COMPREHENSIVE_THEMING: false +ENTERPRISE_API_URL: http://edx.devstack.lms:18000/enterprise/api/v1 +ENTERPRISE_MARKETING_FOOTER_QUERY_PARAMS: {} +ENTERPRISE_SERVICE_WORKER_USERNAME: enterprise_worker +EVENT_TRACKING_SEGMENTIO_EMIT_WHITELIST: [] +EXTRA_MIDDLEWARE_CLASSES: [] +FACEBOOK_API_VERSION: v2.1 +FACEBOOK_APP_ID: FACEBOOK_APP_ID +FACEBOOK_APP_SECRET: FACEBOOK_APP_SECRET +FEATURES: + AUTH_USE_OPENID_PROVIDER: true + AUTOMATIC_AUTH_FOR_TESTING: false + CUSTOM_COURSES_EDX: false + ENABLE_BULK_ENROLLMENT_VIEW: false + ENABLE_COMBINED_LOGIN_REGISTRATION: true + ENABLE_CORS_HEADERS: false + ENABLE_COUNTRY_ACCESS: false + ENABLE_CREDIT_API: false + ENABLE_CREDIT_ELIGIBILITY: false + ENABLE_CROSS_DOMAIN_CSRF_COOKIE: false + ENABLE_CSMH_EXTENDED: true + ENABLE_DISCUSSION_HOME_PANEL: true + ENABLE_DISCUSSION_SERVICE: true + ENABLE_EDXNOTES: true + ENABLE_ENROLLMENT_RESET: false + ENABLE_EXPORT_GIT: false + ENABLE_GRADE_DOWNLOADS: true + ENABLE_LTI_PROVIDER: false + ENABLE_MKTG_SITE: false + ENABLE_MOBILE_REST_API: false + ENABLE_OAUTH2_PROVIDER: false + ENABLE_PUBLISHER: false + ENABLE_READING_FROM_MULTIPLE_HISTORY_TABLES: true + ENABLE_SPECIAL_EXAMS: false + ENABLE_SYSADMIN_DASHBOARD: false + ENABLE_THIRD_PARTY_AUTH: true + ENABLE_VIDEO_UPLOAD_PIPELINE: false + PREVIEW_LMS_BASE: preview.localhost:18000 + SHOW_FOOTER_LANGUAGE_SELECTOR: false + SHOW_HEADER_LANGUAGE_SELECTOR: false +FEEDBACK_SUBMISSION_EMAIL: '' +FERNET_KEYS: +- DUMMY KEY CHANGE BEFORE GOING TO PRODUCTION +FILE_UPLOAD_STORAGE_BUCKET_NAME: SET-ME-PLEASE (ex. bucket-name) +FILE_UPLOAD_STORAGE_PREFIX: submissions_attachments +FINANCIAL_REPORTS: + BUCKET: null + ROOT_PATH: sandbox + STORAGE_TYPE: localfs +FOOTER_ORGANIZATION_IMAGE: images/logo.png +GITHUB_REPO_ROOT: /edx/var/edxapp/data +GIT_REPO_EXPORT_DIR: /edx/var/edxapp/export_course_repos +GOOGLE_ANALYTICS_ACCOUNT: null +GRADES_DOWNLOAD: + BUCKET: '' + ROOT_PATH: '' + STORAGE_CLASS: django.core.files.storage.FileSystemStorage + STORAGE_KWARGS: + location: /tmp/edx-s3/grades + STORAGE_TYPE: '' +HELP_TOKENS_BOOKS: + course_author: http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course + learner: http://edx.readthedocs.io/projects/open-edx-learner-guide +ICP_LICENSE: null +ICP_LICENSE_INFO: {} +IDA_LOGOUT_URI_LIST: [] +ID_VERIFICATION_SUPPORT_LINK: '' +INTEGRATED_CHANNELS_API_CHUNK_TRANSMISSION_LIMIT: + SAP: 1 +JWT_AUTH: + JWT_AUDIENCE: lms-key + JWT_AUTH_COOKIE_HEADER_PAYLOAD: edx-jwt-cookie-header-payload + JWT_AUTH_COOKIE_SIGNATURE: edx-jwt-cookie-signature + JWT_AUTH_REFRESH_COOKIE: edx-jwt-refresh-cookie + JWT_ISSUER: http://edx.devstack.lms:18000/oauth2 + JWT_ISSUERS: + - AUDIENCE: lms-key + ISSUER: http://edx.devstack.lms:18000/oauth2 + SECRET_KEY: lms-secret + JWT_PRIVATE_SIGNING_JWK: None + JWT_PUBLIC_SIGNING_JWK_SET: '' + JWT_SECRET_KEY: lms-secret + JWT_SIGNING_ALGORITHM: null +JWT_EXPIRATION: 30 +JWT_ISSUER: http://edx.devstack.lms:18000/oauth2 +JWT_PRIVATE_SIGNING_KEY: null +LANGUAGE_CODE: en +LANGUAGE_COOKIE: openedx-language-preference +LEARNER_PORTAL_URL_ROOT: https://learner-portal-edx.devstack.lms:18000 +LMS_BASE: edx.devstack.lms:18000 +LMS_INTERNAL_ROOT_URL: http://edx.devstack.lms:18000 +LMS_ROOT_URL: http://edx.devstack.lms:18000 +LOCAL_LOGLEVEL: INFO +LOGGING_ENV: sandbox +LOGIN_REDIRECT_WHITELIST: [] +LOG_DIR: /edx/var/log/edx +MAINTENANCE_BANNER_TEXT: Sample banner message +MEDIA_ROOT: /edx/var/edxapp/media/ +MEDIA_URL: /media/ +MICROSITE_CONFIGURATION: {} +MICROSITE_ROOT_DIR: /edx/app/edxapp/edx-microsite +MKTG_URLS: {} +MKTG_URL_LINK_MAP: {} +MOBILE_STORE_URLS: {} +MODULESTORE: + default: + ENGINE: xmodule.modulestore.mixed.MixedModuleStore + OPTIONS: + mappings: {} + stores: + - DOC_STORE_CONFIG: + authsource: '' + collection: modulestore + connectTimeoutMS: 2000 + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + read_preference: PRIMARY + replicaSet: '' + socketTimeoutMS: 3000 + ssl: false + user: edxapp + ENGINE: xmodule.modulestore.split_mongo.split_draft.DraftVersioningModuleStore + NAME: split + OPTIONS: + default_class: xmodule.hidden_module.HiddenDescriptor + fs_root: /edx/var/edxapp/data + render_template: common.djangoapps.edxmako.shortcuts.render_to_string + - DOC_STORE_CONFIG: + authsource: '' + collection: modulestore + connectTimeoutMS: 2000 + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + read_preference: PRIMARY + replicaSet: '' + socketTimeoutMS: 3000 + ssl: false + user: edxapp + ENGINE: xmodule.modulestore.mongo.DraftMongoModuleStore + NAME: draft + OPTIONS: + default_class: xmodule.hidden_module.HiddenDescriptor + fs_root: /edx/var/edxapp/data + render_template: common.djangoapps.edxmako.shortcuts.render_to_string +ORA2_FILE_PREFIX: default_env-default_deployment/ora2 +PARSE_KEYS: {} +PARTNER_SUPPORT_EMAIL: '' +PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG: + ENFORCE_COMPLIANCE_ON_LOGIN: false +PASSWORD_RESET_SUPPORT_LINK: '' +PAYMENT_SUPPORT_EMAIL: billing@example.com +PLATFORM_DESCRIPTION: Your Platform Description Here +PLATFORM_FACEBOOK_ACCOUNT: http://www.facebook.com/YourPlatformFacebookAccount +PLATFORM_NAME: Your Platform Name Here +PLATFORM_TWITTER_ACCOUNT: '@YourPlatformTwitterAccount' +POLICY_CHANGE_GRADES_ROUTING_KEY: edx.lms.core.default +PRESS_EMAIL: press@example.com +PROCTORING_BACKENDS: + DEFAULT: 'null' + 'null': {} +PROCTORING_SETTINGS: {} +REGISTRATION_EXTRA_FIELDS: + city: hidden + confirm_email: hidden + country: required + gender: optional + goals: optional + honor_code: required + level_of_education: optional + mailing_address: hidden + terms_of_service: hidden + year_of_birth: optional +RETIRED_EMAIL_DOMAIN: retired.invalid +RETIRED_EMAIL_PREFIX: retired__user_ +RETIRED_USERNAME_PREFIX: retired__user_ +RETIRED_USER_SALTS: +- OVERRIDE ME WITH A RANDOM VALUE +- ROTATE SALTS BY APPENDING NEW VALUES +RETIREMENT_SERVICE_WORKER_USERNAME: retirement_worker +RETIREMENT_STATES: +- PENDING +- ERRORED +- ABORTED +- COMPLETE +SECRET_KEY: DUMMY KEY ONLY FOR TO DEVSTACK +SEGMENT_KEY: null +SERVER_EMAIL: sre@example.com +SESSION_COOKIE_DOMAIN: '' +SESSION_COOKIE_NAME: sessionid +SESSION_COOKIE_SECURE: false +SESSION_SAVE_EVERY_REQUEST: false +SITE_NAME: localhost +SOCIAL_AUTH_SAML_SP_PRIVATE_KEY: '' +SOCIAL_AUTH_SAML_SP_PRIVATE_KEY_DICT: {} +SOCIAL_AUTH_SAML_SP_PUBLIC_CERT: '' +SOCIAL_AUTH_SAML_SP_PUBLIC_CERT_DICT: {} +SOCIAL_MEDIA_FOOTER_URLS: {} +SOCIAL_SHARING_SETTINGS: + CERTIFICATE_FACEBOOK: false + CERTIFICATE_TWITTER: false + CUSTOM_COURSE_URLS: false + DASHBOARD_FACEBOOK: false + DASHBOARD_TWITTER: false +STATIC_ROOT_BASE: /edx/var/edxapp/staticfiles +STATIC_URL_BASE: /static/ +STUDIO_NAME: Studio +STUDIO_SHORT_NAME: Studio +SUPPORT_SITE_LINK: '' +SWIFT_AUTH_URL: null +SWIFT_AUTH_VERSION: null +SWIFT_KEY: null +SWIFT_REGION_NAME: null +SWIFT_TEMP_URL_DURATION: 1800 +SWIFT_TEMP_URL_KEY: null +SWIFT_TENANT_ID: null +SWIFT_TENANT_NAME: null +SWIFT_USERNAME: null +SWIFT_USE_TEMP_URLS: false +SYSLOG_SERVER: '' +SYSTEM_WIDE_ROLE_CLASSES: [] +TECH_SUPPORT_EMAIL: technical@example.com +TIME_ZONE: America/New_York +UNIVERSITY_EMAIL: university@example.com +USERNAME_REPLACEMENT_WORKER: OVERRIDE THIS WITH A VALID USERNAME +VIDEO_IMAGE_MAX_AGE: 31536000 +VIDEO_IMAGE_SETTINGS: + DIRECTORY_PREFIX: video-images/ + STORAGE_KWARGS: + base_url: /media/ + location: /edx/var/edxapp/media// + VIDEO_IMAGE_MAX_BYTES: 2097152 + VIDEO_IMAGE_MIN_BYTES: 2048 +VIDEO_TRANSCRIPTS_MAX_AGE: 31536000 +VIDEO_TRANSCRIPTS_SETTINGS: + DIRECTORY_PREFIX: video-transcripts/ + STORAGE_KWARGS: + base_url: /media/ + location: /edx/var/edxapp/media// + VIDEO_TRANSCRIPTS_MAX_BYTES: 3145728 +VIDEO_UPLOAD_PIPELINE: + BUCKET: '' + ROOT_PATH: '' +WIKI_ENABLED: true +XBLOCK_FS_STORAGE_BUCKET: null +XBLOCK_FS_STORAGE_PREFIX: null +XBLOCK_SETTINGS: {} +XQUEUE_INTERFACE: + basic_auth: + - edx + - edx + django_auth: + password: password + username: lms + url: http://edx.devstack.xqueue:18040 +X_FRAME_OPTIONS: DENY +YOUTUBE_API_KEY: PUT_YOUR_API_KEY_HERE +ZENDESK_API_KEY: '' +ZENDESK_CUSTOM_FIELDS: {} +ZENDESK_GROUP_ID_MAPPING: {} +ZENDESK_OAUTH_ACCESS_TOKEN: '' +ZENDESK_URL: '' +ZENDESK_USER: '' diff --git a/lms/envs/devstack-experimental.yml b/lms/envs/devstack-experimental.yml new file mode 100644 index 0000000000..cf8020e1fe --- /dev/null +++ b/lms/envs/devstack-experimental.yml @@ -0,0 +1,626 @@ +# This file is an experimental extraction of /edx/etc/lms.yml from +# a LMS devstack container. +# +# When devstack is configured to use the new `openedx/` images +# instead of the old `edxops/edxapp` image, it will use this file +# as input to lms/envs/production.py (and, in turn, lms/envs/devstack.py). +# If you are using devstack with the `edxops/edxapp` image, though, +# this file is NOT used. +# +# Q. Should I update this file when I update devstack.py? +# A. You don't *have* to, because settings in devstack.py +# override these settings. But, it doesn't harm to also make them +# here in order to quell confusion. The hope is that we'll +# adpot OEP-45 eventually, which recommends against having +# a devstack.py at all. +# +# This is part of the effort to move our dev tools off of Ansible and +# Paver, described here: https://github.com/edx/devstack/pull/866 +# TODO: If the effort described above is abandoned, then this file should +# probably be deleted. +ACCOUNT_MICROFRONTEND_URL: null +ACE_CHANNEL_DEFAULT_EMAIL: django_email +ACE_CHANNEL_SAILTHRU_API_KEY: '' +ACE_CHANNEL_SAILTHRU_API_SECRET: '' +ACE_CHANNEL_SAILTHRU_DEBUG: true +ACE_CHANNEL_SAILTHRU_TEMPLATE_NAME: null +ACE_CHANNEL_TRANSACTIONAL_EMAIL: django_email +ACE_ENABLED_CHANNELS: +- django_email +ACE_ENABLED_POLICIES: +- bulk_email_optout +ACE_ROUTING_KEY: edx.lms.core.default +ACTIVATION_EMAIL_SUPPORT_LINK: '' +AFFILIATE_COOKIE_NAME: dev_affiliate_id +ALTERNATE_WORKER_QUEUES: cms +ANALYTICS_API_KEY: '' +ANALYTICS_API_URL: http://localhost:18100 +ANALYTICS_DASHBOARD_NAME: Your Platform Name Here Insights +ANALYTICS_DASHBOARD_URL: http://localhost:18110/courses +API_ACCESS_FROM_EMAIL: api-requests@example.com +API_ACCESS_MANAGER_EMAIL: api-access@example.com +API_DOCUMENTATION_URL: http://course-catalog-api-guide.readthedocs.io/en/latest/ +AUTH_DOCUMENTATION_URL: http://course-catalog-api-guide.readthedocs.io/en/latest/authentication/index.html +AUTH_PASSWORD_VALIDATORS: +- NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator +- NAME: common.djangoapps.util.password_policy_validators.MinimumLengthValidator + OPTIONS: + min_length: 2 +- NAME: common.djangoapps.util.password_policy_validators.MaximumLengthValidator + OPTIONS: + max_length: 75 +AWS_ACCESS_KEY_ID: null +AWS_QUERYSTRING_AUTH: false +AWS_S3_CUSTOM_DOMAIN: SET-ME-PLEASE (ex. bucket-name.s3.amazonaws.com) +AWS_SECRET_ACCESS_KEY: null +AWS_SES_REGION_ENDPOINT: email.us-east-1.amazonaws.com +AWS_SES_REGION_NAME: us-east-1 +AWS_STORAGE_BUCKET_NAME: SET-ME-PLEASE (ex. bucket-name) +BASE_COOKIE_DOMAIN: localhost +BLOCKSTORE_API_URL: http://localhost:18250/api/v1 +BLOCKSTORE_PUBLIC_URL_ROOT: http://localhost:18250 +BLOCK_STRUCTURES_SETTINGS: + COURSE_PUBLISH_TASK_DELAY: 30 + PRUNING_ACTIVE: false + TASK_DEFAULT_RETRY_DELAY: 30 + TASK_MAX_RETRIES: 5 +BRANCH_IO_KEY: '' +BUGS_EMAIL: bugs@example.com +BULK_EMAIL_DEFAULT_FROM_EMAIL: no-reply@example.com +BULK_EMAIL_EMAILS_PER_TASK: 500 +BULK_EMAIL_LOG_SENT_EMAILS: false +BULK_EMAIL_ROUTING_KEY_SMALL_JOBS: edx.lms.core.default +CACHES: + celery: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: celery + LOCATION: + - edx.devstack.memcached:11211 + TIMEOUT: '7200' + configuration: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: 78f87108afce + LOCATION: + - edx.devstack.memcached:11211 + course_structure_cache: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: course_structure + LOCATION: + - edx.devstack.memcached:11211 + TIMEOUT: '7200' + default: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: default + LOCATION: + - edx.devstack.memcached:11211 + VERSION: '1' + general: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: general + LOCATION: + - edx.devstack.memcached:11211 + mongo_metadata_inheritance: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: mongo_metadata_inheritance + LOCATION: + - edx.devstack.memcached:11211 + TIMEOUT: 300 + staticfiles: + BACKEND: django.core.cache.backends.memcached.MemcachedCache + KEY_FUNCTION: common.djangoapps.util.memcache.safe_key + KEY_PREFIX: 78f87108afce_general + LOCATION: + - edx.devstack.memcached:11211 +CAS_ATTRIBUTE_CALLBACK: '' +CAS_EXTRA_LOGIN_PARAMS: '' +CAS_SERVER_URL: '' +CELERYBEAT_SCHEDULER: celery.beat:PersistentScheduler +CELERY_BROKER_HOSTNAME: localhost +CELERY_BROKER_PASSWORD: '' +CELERY_BROKER_TRANSPORT: redis +CELERY_BROKER_USER: '' +CELERY_BROKER_USE_SSL: false +CELERY_BROKER_VHOST: '' +CELERY_EVENT_QUEUE_TTL: null +CELERY_QUEUES: +- edx.lms.core.default +- edx.lms.core.high +- edx.lms.core.high_mem +CELERY_TIMEZONE: UTC +CERTIFICATE_TEMPLATE_LANGUAGES: + en: English + es: Español +CERT_QUEUE: certificates +CMS_BASE: edx.devstack.studio:18010 +CODE_JAIL: + limits: + CPU: 1 + FSIZE: 1048576 + PROXY: 0 + REALTIME: 3 + VMEM: 536870912 + python_bin: /edx/app/edxapp/venvs/edxapp-sandbox/bin/python + user: sandbox +COMMENTS_SERVICE_KEY: password +COMMENTS_SERVICE_URL: http://localhost:18080 +COMPREHENSIVE_THEME_DIRS: +- '' +COMPREHENSIVE_THEME_LOCALE_PATHS: [] +CONTACT_EMAIL: info@example.com +CONTACT_MAILING_ADDRESS: SET-ME-PLEASE +CONTENTSTORE: + ADDITIONAL_OPTIONS: {} + DOC_STORE_CONFIG: + authsource: '' + collection: modulestore + connectTimeoutMS: 2000 + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + read_preference: SECONDARY_PREFERRED + replicaSet: '' + socketTimeoutMS: 3000 + ssl: false + user: edxapp + ENGINE: xmodule.contentstore.mongo.MongoContentStore + OPTIONS: + auth_source: '' + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + ssl: false + user: edxapp +CORS_ORIGIN_ALLOW_ALL: false +CORS_ORIGIN_WHITELIST: [] +COURSES_WITH_UNSAFE_CODE: [] +COURSE_ABOUT_VISIBILITY_PERMISSION: see_exists +COURSE_CATALOG_API_URL: http://localhost:8008/api/v1 +COURSE_CATALOG_URL_ROOT: http://localhost:8008 +COURSE_CATALOG_VISIBILITY_PERMISSION: see_exists +CREDENTIALS_INTERNAL_SERVICE_URL: http://localhost:8005 +CREDENTIALS_PUBLIC_SERVICE_URL: http://localhost:8005 +CREDIT_HELP_LINK_URL: '' +CREDIT_PROVIDER_SECRET_KEYS: {} +CROSS_DOMAIN_CSRF_COOKIE_DOMAIN: '' +CROSS_DOMAIN_CSRF_COOKIE_NAME: '' +CSRF_COOKIE_SECURE: false +CSRF_TRUSTED_ORIGINS: [] +DASHBOARD_COURSE_LIMIT: null +DATABASES: + default: + ATOMIC_REQUESTS: true + CONN_MAX_AGE: 0 + ENGINE: django.db.backends.mysql + HOST: edx.devstack.mysql57 + NAME: edxapp + OPTIONS: + isolation_level: read committed + PASSWORD: password + PORT: '3306' + USER: edxapp001 + read_replica: + CONN_MAX_AGE: 0 + ENGINE: django.db.backends.mysql + HOST: edx.devstack.mysql57 + NAME: edxapp + OPTIONS: + isolation_level: read committed + PASSWORD: password + PORT: '3306' + USER: edxapp001 + student_module_history: + CONN_MAX_AGE: 0 + ENGINE: django.db.backends.mysql + HOST: edx.devstack.mysql57 + NAME: edxapp_csmh + OPTIONS: + isolation_level: read committed + PASSWORD: password + PORT: '3306' + USER: edxapp001 +DATA_DIR: /edx/var/edxapp +DCS_SESSION_COOKIE_SAMESITE: Lax +DCS_SESSION_COOKIE_SAMESITE_FORCE_ALL: true +DEFAULT_COURSE_VISIBILITY_IN_CATALOG: both +DEFAULT_FEEDBACK_EMAIL: feedback@example.com +DEFAULT_FILE_STORAGE: django.core.files.storage.FileSystemStorage +DEFAULT_FROM_EMAIL: registration@example.com +DEFAULT_JWT_ISSUER: + AUDIENCE: lms-key + ISSUER: http://edx.devstack.lms:18000/oauth2 + SECRET_KEY: lms-secret +DEFAULT_MOBILE_AVAILABLE: false +DEFAULT_SITE_THEME: '' +DEPRECATED_ADVANCED_COMPONENT_TYPES: [] +DJFS: + directory_root: /edx/var/edxapp/django-pyfs/static/django-pyfs + type: osfs + url_root: /static/django-pyfs +DOC_STORE_CONFIG: + authsource: '' + collection: modulestore + connectTimeoutMS: 2000 + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + read_preference: SECONDARY_PREFERRED + replicaSet: '' + socketTimeoutMS: 3000 + ssl: false + user: edxapp +ECOMMERCE_API_SIGNING_KEY: lms-secret +ECOMMERCE_API_URL: http://localhost:8002/api/v2 +ECOMMERCE_PUBLIC_URL_ROOT: http://localhost:8002 +EDXMKTG_USER_INFO_COOKIE_NAME: edx-user-info +EDXNOTES_INTERNAL_API: http://edx.devstack.edx_notes_api:18120/api/v1 +EDXNOTES_PUBLIC_API: http://localhost:18120/api/v1 +EDX_API_KEY: PUT_YOUR_API_KEY_HERE +EDX_PLATFORM_REVISION: master +ELASTIC_SEARCH_CONFIG: +- host: edx.devstack.elasticsearch + port: 9200 + use_ssl: false +EMAIL_BACKEND: django.core.mail.backends.smtp.EmailBackend +EMAIL_HOST: localhost +EMAIL_HOST_PASSWORD: '' +EMAIL_HOST_USER: '' +EMAIL_PORT: 25 +EMAIL_USE_TLS: false +ENABLE_COMPREHENSIVE_THEMING: false +ENTERPRISE_API_URL: http://edx.devstack.lms:18000/enterprise/api/v1 +ENTERPRISE_COURSE_ENROLLMENT_AUDIT_MODES: +- audit +- honor +ENTERPRISE_CUSTOMER_SUCCESS_EMAIL: customersuccess@edx.org +ENTERPRISE_ENROLLMENT_API_URL: http://edx.devstack.lms:18000/api/enrollment/v1/ +ENTERPRISE_INTEGRATIONS_EMAIL: enterprise-integrations@edx.org +ENTERPRISE_MARKETING_FOOTER_QUERY_PARAMS: {} +ENTERPRISE_SERVICE_WORKER_USERNAME: enterprise_worker +ENTERPRISE_SUPPORT_URL: '' +ENTERPRISE_TAGLINE: '' +EVENT_TRACKING_SEGMENTIO_EMIT_WHITELIST: [] +EXTRA_MIDDLEWARE_CLASSES: [] +FACEBOOK_API_VERSION: v2.1 +FACEBOOK_APP_ID: FACEBOOK_APP_ID +FACEBOOK_APP_SECRET: FACEBOOK_APP_SECRET +FEATURES: + AUTH_USE_OPENID_PROVIDER: true + AUTOMATIC_AUTH_FOR_TESTING: false + CUSTOM_COURSES_EDX: false + ENABLE_BULK_ENROLLMENT_VIEW: false + ENABLE_COMBINED_LOGIN_REGISTRATION: true + ENABLE_CORS_HEADERS: false + ENABLE_COUNTRY_ACCESS: false + ENABLE_CREDIT_API: false + ENABLE_CREDIT_ELIGIBILITY: false + ENABLE_CROSS_DOMAIN_CSRF_COOKIE: false + ENABLE_CSMH_EXTENDED: true + ENABLE_DISCUSSION_HOME_PANEL: true + ENABLE_DISCUSSION_SERVICE: true + ENABLE_EDXNOTES: true + ENABLE_ENROLLMENT_RESET: false + ENABLE_EXPORT_GIT: false + ENABLE_GRADE_DOWNLOADS: true + ENABLE_LTI_PROVIDER: false + ENABLE_MKTG_SITE: false + ENABLE_MOBILE_REST_API: false + ENABLE_OAUTH2_PROVIDER: false + ENABLE_PUBLISHER: false + ENABLE_READING_FROM_MULTIPLE_HISTORY_TABLES: true + ENABLE_SPECIAL_EXAMS: false + ENABLE_SYSADMIN_DASHBOARD: false + ENABLE_THIRD_PARTY_AUTH: true + ENABLE_VIDEO_UPLOAD_PIPELINE: false + PREVIEW_LMS_BASE: preview.localhost:18000 + SHOW_FOOTER_LANGUAGE_SELECTOR: false + SHOW_HEADER_LANGUAGE_SELECTOR: false +FEEDBACK_SUBMISSION_EMAIL: '' +FERNET_KEYS: +- DUMMY KEY CHANGE BEFORE GOING TO PRODUCTION +FILE_UPLOAD_STORAGE_BUCKET_NAME: SET-ME-PLEASE (ex. bucket-name) +FILE_UPLOAD_STORAGE_PREFIX: submissions_attachments +FINANCIAL_REPORTS: + BUCKET: null + ROOT_PATH: sandbox + STORAGE_TYPE: localfs +FOOTER_ORGANIZATION_IMAGE: images/logo.png +GITHUB_REPO_ROOT: /edx/var/edxapp/data +GIT_REPO_DIR: /edx/var/edxapp/course_repos +GOOGLE_ANALYTICS_ACCOUNT: null +GOOGLE_ANALYTICS_LINKEDIN: '' +GOOGLE_ANALYTICS_TRACKING_ID: '' +GOOGLE_SITE_VERIFICATION_ID: '' +GRADES_DOWNLOAD: + BUCKET: '' + ROOT_PATH: '' + STORAGE_CLASS: django.core.files.storage.FileSystemStorage + STORAGE_KWARGS: + location: /tmp/edx-s3/grades + STORAGE_TYPE: '' +HELP_TOKENS_BOOKS: + course_author: http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course + learner: http://edx.readthedocs.io/projects/open-edx-learner-guide +HTTPS: 'on' +ICP_LICENSE: null +ICP_LICENSE_INFO: {} +IDA_LOGOUT_URI_LIST: [] +ID_VERIFICATION_SUPPORT_LINK: '' +INTEGRATED_CHANNELS_API_CHUNK_TRANSMISSION_LIMIT: + SAP: 1 +JWT_AUTH: + JWT_AUDIENCE: lms-key + JWT_AUTH_COOKIE_HEADER_PAYLOAD: edx-jwt-cookie-header-payload + JWT_AUTH_COOKIE_SIGNATURE: edx-jwt-cookie-signature + JWT_AUTH_REFRESH_COOKIE: edx-jwt-refresh-cookie + JWT_ISSUER: http://edx.devstack.lms:18000/oauth2 + JWT_ISSUERS: + - AUDIENCE: lms-key + ISSUER: http://edx.devstack.lms:18000/oauth2 + SECRET_KEY: lms-secret + JWT_PRIVATE_SIGNING_JWK: None + JWT_PUBLIC_SIGNING_JWK_SET: '' + JWT_SECRET_KEY: lms-secret + JWT_SIGNING_ALGORITHM: null +JWT_EXPIRATION: 30 +JWT_ISSUER: http://edx.devstack.lms:18000/oauth2 +JWT_PRIVATE_SIGNING_KEY: null +LANGUAGE_CODE: en +LANGUAGE_COOKIE: openedx-language-preference +LEARNER_PORTAL_URL_ROOT: https://learner-portal-edx.devstack.lms:18000 +LEARNING_MICROFRONTEND_URL: null +LMS_BASE: edx.devstack.lms:18000 +LMS_INTERNAL_ROOT_URL: http://edx.devstack.lms:18000 +LMS_ROOT_URL: http://edx.devstack.lms:18000 +LOCAL_LOGLEVEL: INFO +LOGGING_ENV: sandbox +LOGIN_REDIRECT_WHITELIST: [] +LOG_DIR: /edx/var/log/edx +LTI_AGGREGATE_SCORE_PASSBACK_DELAY: 900 +LTI_USER_EMAIL_DOMAIN: lti.example.com +MAILCHIMP_NEW_USER_LIST_ID: null +MAINTENANCE_BANNER_TEXT: Sample banner message +MEDIA_ROOT: /edx/var/edxapp/media/ +MEDIA_URL: /media/ +MICROSITE_CONFIGURATION: {} +MICROSITE_ROOT_DIR: /edx/app/edxapp/edx-microsite +MKTG_URLS: {} +MKTG_URL_LINK_MAP: {} +MOBILE_STORE_URLS: {} +MODULESTORE: + default: + ENGINE: xmodule.modulestore.mixed.MixedModuleStore + OPTIONS: + mappings: {} + stores: + - DOC_STORE_CONFIG: + authsource: '' + collection: modulestore + connectTimeoutMS: 2000 + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + read_preference: SECONDARY_PREFERRED + replicaSet: '' + socketTimeoutMS: 3000 + ssl: false + user: edxapp + ENGINE: xmodule.modulestore.split_mongo.split_draft.DraftVersioningModuleStore + NAME: split + OPTIONS: + default_class: xmodule.hidden_module.HiddenDescriptor + fs_root: /edx/var/edxapp/data + render_template: common.djangoapps.edxmako.shortcuts.render_to_string + - DOC_STORE_CONFIG: + authsource: '' + collection: modulestore + connectTimeoutMS: 2000 + db: edxapp + host: + - edx.devstack.mongo + password: password + port: 27017 + read_preference: PRIMARY + replicaSet: '' + socketTimeoutMS: 3000 + ssl: false + user: edxapp + ENGINE: xmodule.modulestore.mongo.DraftMongoModuleStore + NAME: draft + OPTIONS: + default_class: xmodule.hidden_module.HiddenDescriptor + fs_root: /edx/var/edxapp/data + render_template: common.djangoapps.edxmako.shortcuts.render_to_string +OAUTH_DELETE_EXPIRED: true +OAUTH_ENFORCE_SECURE: false +OAUTH_EXPIRE_CONFIDENTIAL_CLIENT_DAYS: 365 +OAUTH_EXPIRE_PUBLIC_CLIENT_DAYS: 30 +OPTIMIZELY_PROJECT_ID: null +ORA2_FILE_PREFIX: default_env-default_deployment/ora2 +ORDER_HISTORY_MICROFRONTEND_URL: null +ORGANIZATIONS_AUTOCREATE: true +PAID_COURSE_REGISTRATION_CURRENCY: +- usd +- $ +PARENTAL_CONSENT_AGE_LIMIT: 13 +PARTNER_SUPPORT_EMAIL: '' +PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG: + ENFORCE_COMPLIANCE_ON_LOGIN: false +PASSWORD_RESET_SUPPORT_LINK: '' +PAYMENT_SUPPORT_EMAIL: billing@example.com +PDF_RECEIPT_BILLING_ADDRESS: 'Enter your receipt billing + + address here. + + ' +PDF_RECEIPT_COBRAND_LOGO_PATH: '' +PDF_RECEIPT_DISCLAIMER_TEXT: 'ENTER YOUR RECEIPT DISCLAIMER TEXT HERE. + + ' +PDF_RECEIPT_FOOTER_TEXT: 'Enter your receipt footer text here. + + ' +PDF_RECEIPT_LOGO_PATH: '' +PDF_RECEIPT_TAX_ID: 00-0000000 +PDF_RECEIPT_TAX_ID_LABEL: fake Tax ID +PDF_RECEIPT_TERMS_AND_CONDITIONS: 'Enter your receipt terms and conditions here. + + ' +PLATFORM_DESCRIPTION: Your Platform Description Here +PLATFORM_FACEBOOK_ACCOUNT: http://www.facebook.com/YourPlatformFacebookAccount +PLATFORM_NAME: Your Platform Name Here +PLATFORM_TWITTER_ACCOUNT: '@YourPlatformTwitterAccount' +POLICY_CHANGE_GRADES_ROUTING_KEY: edx.lms.core.default +PRESS_EMAIL: press@example.com +PROCTORING_BACKENDS: + DEFAULT: 'null' + 'null': {} +PROCTORING_SETTINGS: {} +PROFILE_IMAGE_BACKEND: + class: openedx.core.storage.OverwriteStorage + options: + base_url: /media/profile-images/ + location: /edx/var/edxapp/media/profile-images/ +PROFILE_IMAGE_HASH_SEED: placeholder_secret_key +PROFILE_IMAGE_MAX_BYTES: 1048576 +PROFILE_IMAGE_MIN_BYTES: 100 +PROFILE_IMAGE_SIZES_MAP: + full: 500 + large: 120 + medium: 50 + small: 30 +PROFILE_MICROFRONTEND_URL: null +PROGRAM_CERTIFICATES_ROUTING_KEY: edx.lms.core.default +PROGRAM_CONSOLE_MICROFRONTEND_URL: null +RECALCULATE_GRADES_ROUTING_KEY: edx.lms.core.default +REGISTRATION_EXTRA_FIELDS: + city: hidden + confirm_email: hidden + country: required + gender: optional + goals: optional + honor_code: required + level_of_education: optional + mailing_address: hidden + terms_of_service: hidden + year_of_birth: optional +RETIRED_EMAIL_DOMAIN: retired.invalid +RETIRED_EMAIL_PREFIX: retired__user_ +RETIRED_USERNAME_PREFIX: retired__user_ +RETIRED_USER_SALTS: +- OVERRIDE ME WITH A RANDOM VALUE +- ROTATE SALTS BY APPENDING NEW VALUES +RETIREMENT_SERVICE_WORKER_USERNAME: retirement_worker +RETIREMENT_STATES: +- PENDING +- ERRORED +- ABORTED +- COMPLETE +SECRET_KEY: DUMMY KEY ONLY FOR TO DEVSTACK +SEGMENT_KEY: null +SERVER_EMAIL: sre@example.com +SESSION_COOKIE_DOMAIN: '' +SESSION_COOKIE_NAME: sessionid +SESSION_COOKIE_SECURE: false +SESSION_SAVE_EVERY_REQUEST: false +SITE_NAME: localhost +SOCIAL_AUTH_OAUTH_SECRETS: '' +SOCIAL_AUTH_SAML_SP_PRIVATE_KEY: '' +SOCIAL_AUTH_SAML_SP_PRIVATE_KEY_DICT: {} +SOCIAL_AUTH_SAML_SP_PUBLIC_CERT: '' +SOCIAL_AUTH_SAML_SP_PUBLIC_CERT_DICT: {} +SOCIAL_MEDIA_FOOTER_URLS: {} +SOCIAL_SHARING_SETTINGS: + CERTIFICATE_FACEBOOK: false + CERTIFICATE_TWITTER: false + CUSTOM_COURSE_URLS: false + DASHBOARD_FACEBOOK: false + DASHBOARD_TWITTER: false +STATIC_ROOT_BASE: /edx/var/edxapp/staticfiles +STATIC_URL_BASE: /static/ +STUDIO_NAME: Studio +STUDIO_SHORT_NAME: Studio +SUPPORT_SITE_LINK: '' +SWIFT_AUTH_URL: null +SWIFT_AUTH_VERSION: null +SWIFT_KEY: null +SWIFT_REGION_NAME: null +SWIFT_TEMP_URL_DURATION: 1800 +SWIFT_TEMP_URL_KEY: null +SWIFT_TENANT_ID: null +SWIFT_TENANT_NAME: null +SWIFT_USERNAME: null +SWIFT_USE_TEMP_URLS: false +SYSLOG_SERVER: '' +SYSTEM_WIDE_ROLE_CLASSES: [] +TECH_SUPPORT_EMAIL: technical@example.com +THIRD_PARTY_AUTH_BACKENDS: +- social_core.backends.google.GoogleOAuth2 +- social_core.backends.linkedin.LinkedinOAuth2 +- social_core.backends.facebook.FacebookOAuth2 +- social_core.backends.azuread.AzureADOAuth2 +- common.djangoapps.third_party_auth.appleid.AppleIdAuth +- common.djangoapps.third_party_auth.identityserver3.IdentityServer3 +- common.djangoapps.third_party_auth.saml.SAMLAuthBackend +- common.djangoapps.third_party_auth.lti.LTIAuthBackend +TIME_ZONE: America/New_York +TRACKING_SEGMENTIO_WEBHOOK_SECRET: '' +UNIVERSITY_EMAIL: university@example.com +USERNAME_REPLACEMENT_WORKER: OVERRIDE THIS WITH A VALID USERNAME +VERIFY_STUDENT: + DAYS_GOOD_FOR: 365 + EXPIRING_SOON_WINDOW: 28 +VIDEO_CDN_URL: + EXAMPLE_COUNTRY_CODE: http://example.com/edx/video?s3_url= +VIDEO_IMAGE_MAX_AGE: 31536000 +VIDEO_IMAGE_SETTINGS: + DIRECTORY_PREFIX: video-images/ + STORAGE_KWARGS: + base_url: /media/ + location: /edx/var/edxapp/media// + VIDEO_IMAGE_MAX_BYTES: 2097152 + VIDEO_IMAGE_MIN_BYTES: 2048 +VIDEO_TRANSCRIPTS_MAX_AGE: 31536000 +VIDEO_TRANSCRIPTS_SETTINGS: + DIRECTORY_PREFIX: video-transcripts/ + STORAGE_KWARGS: + base_url: /media/ + location: /edx/var/edxapp/media// + VIDEO_TRANSCRIPTS_MAX_BYTES: 3145728 +VIDEO_UPLOAD_PIPELINE: + BUCKET: '' + ROOT_PATH: '' +WIKI_ENABLED: true +WRITABLE_GRADEBOOK_URL: null +XBLOCK_FS_STORAGE_BUCKET: null +XBLOCK_FS_STORAGE_PREFIX: null +XBLOCK_SETTINGS: {} +XQUEUE_INTERFACE: + basic_auth: + - edx + - edx + django_auth: + password: password + username: lms + url: http://edx.devstack.xqueue:18040 +X_FRAME_OPTIONS: DENY +YOUTUBE_API_KEY: PUT_YOUR_API_KEY_HERE +ZENDESK_API_KEY: '' +ZENDESK_CUSTOM_FIELDS: {} +ZENDESK_GROUP_ID_MAPPING: {} +ZENDESK_OAUTH_ACCESS_TOKEN: '' +ZENDESK_URL: '' +ZENDESK_USER: '' diff --git a/scripts/provision-demo-course.sh b/scripts/provision-demo-course.sh new file mode 100755 index 0000000000..17e97d4b0d --- /dev/null +++ b/scripts/provision-demo-course.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# Usage: +# In a CMS-enabled container, +# from the directory /edx/app/edxapp/edx-platform, run: +# ./scripts/provision-demo-course.sh +# +# This file is an experimental re-implementation of demo course provisioning +# process defined in this Ansible role: +# https://github.com/edx/configuration/tree/master/playbooks/roles/demo +# +# It was written as part of the effort to move our dev tools off of Ansible and +# Paver, described here: https://github.com/edx/devstack/pull/866 +# TODO: If the effort described above is abandoned, then this script should +# probably be deleted. + +set -xeuo pipefail + +DEMO_COURSE_KEY='course-v1:edX+DemoX+Demo_Course' + +# Delete the demo course clone (if it exists) and then do a shallow re-clone of it. +mkdir -p /edx/app/demo +( + cd /edx/app/demo && + rm -rf edx-demo-course && + git clone https://github.com/edx/edx-demo-course.git --depth 1 +) + +# Import the course. +./manage.py cms import /edx/var/edxapp/data /edx/app/demo/edx-demo-course + diff --git a/scripts/provision-demo-users.sh b/scripts/provision-demo-users.sh new file mode 100755 index 0000000000..150c275ce4 --- /dev/null +++ b/scripts/provision-demo-users.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Usage: +# In an LMS-enabled container, +# from the directory /edx/app/edxapp/edx-platform, run: +# ./scripts/provision-demo-users.sh +# +# This file is an experimental re-implementation of demo user provisioning +# process defined in this Ansible role: +# https://github.com/edx/configuration/tree/master/playbooks/roles/demo +# +# It provisions five users: +# * edx (global superuser) +# * staff (global staff) +# * verified +# * audit +# * honor +# Each of which has {username}@example.com as their email and 'edx' as their password. +# +# It was written as part of the effort to move our dev tools off of Ansible and +# Paver, described here: https://github.com/edx/devstack/pull/866 +# TODO: If the effort described above is abandoned, then this script should +# probably be deleted. + +set -xeuo pipefail + +DEMO_COURSE_KEY='course-v1:edX+DemoX+Demo_Course' + +# Hash of 'edx' password. +DEMO_PASSWORD_HASH='pbkdf2_sha256$20000$TjE34FJjc3vv$0B7GUmH8RwrOc/BvMoxjb5j8EgnWTt3sxorDANeF7Qw=' + +# Create users (if they don't exist) and set passwords. +# 'password_is_edx' is purposefully unquoted so that it expands into two arguments. +password_is_edx="--initial-password-hash $DEMO_PASSWORD_HASH" +./manage.py lms manage_user edx edx@example.com $password_is_edx --superuser +./manage.py lms manage_user staff staff@example.com $password_is_edx --staff +./manage.py lms manage_user verified verified@example.com $password_is_edx +./manage.py lms manage_user audit audit@example.com $password_is_edx +./manage.py lms manage_user honor honor@example.com $password_is_edx + +# Enroll users in demo course. +for username in staff verified audit honor; do + ./manage.py lms enroll_user_in_course -e "${username}@example.com" -c "$DEMO_COURSE_KEY" +done + +# Seed the forums for the demo course. +./manage.py lms seed_permissions_roles "$DEMO_COURSE_KEY" diff --git a/scripts/update-assets-dev.sh b/scripts/update-assets-dev.sh new file mode 100755 index 0000000000..f5c2862688 --- /dev/null +++ b/scripts/update-assets-dev.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +# Usage: +# In a CMS or LMS container, +# from the directory /edx/app/edxapp/edx-platform, run: +# ./scripts/update-assets-dev.sh +# +# This file is an experimental re-implementation of the asset complation process +# defined by the pavelib.assets:update_assets task in +# https://github.com/edx/edx-platform/blob/master/pavelib/assets.py. +# As the script name implies, it is only suited to compile assets for usage +# in a development environment, NOT for production. +# +# It was written as part of the effort to move our dev tools off of Ansible and +# Paver, described here: https://github.com/edx/devstack/pull/866 +# TODO: If the effort described above is abandoned, then this script should +# probably be deleted. + +set -xeuo pipefail + +# Compile assets for baked-in XBlocks that still use the old +# XModule asset pipeline. +# (reimplementing pavelib.assets:process_xmodule_assets) +# `xmodule_assets` complains if `DJANGO_SETTINGS_MODULE` is already set, +# so we set it to empty just for this one invocation. +DJANGO_SETTINGS_MODULE='' xmodule_assets common/static/xmodule + +# Create JS and CSS vendor directories. +# (reimplementing pavelib.assets:process_npm_assets) +mkdir -p common/static/common/js/vendor +mkdir -p common/static/common/css/vendor + +# Copy studio-frontend CSS and JS into vendor directory. +# (reimplementing pavelib.assets:process_npm_assets) +find node_modules/@edx/studio-frontend/dist -type f \( -name \*.css -o -name \*.css.map \) | \ + xargs cp --target-directory=common/static/common/css/vendor +find node_modules/@edx/studio-frontend/dist -type f \! -name \*.css \! -name \*.css.map | \ + xargs cp --target-directory=common/static/common/js/vendor + +# Copy certain NPM JS into vedor directory. +# (reimplementing pavelib.assets:process_npm_assets) +cp -f --target-directory=common/static/common/js/vendor \ + node_modules/backbone.paginator/lib/backbone.paginator.js \ + node_modules/backbone/backbone.js \ + node_modules/bootstrap/dist/js/bootstrap.bundle.js \ + node_modules/hls.js/dist/hls.js \ + node_modules/jquery-migrate/dist/jquery-migrate.js \ + node_modules/jquery.scrollto/jquery.scrollTo.js \ + node_modules/jquery/dist/jquery.js \ + node_modules/moment-timezone/builds/moment-timezone-with-data.js \ + node_modules/moment/min/moment-with-locales.js \ + node_modules/picturefill/dist/picturefill.js \ + node_modules/requirejs/require.js \ + node_modules/underscore.string/dist/underscore.string.js \ + node_modules/underscore/underscore.js \ + node_modules/which-country/index.js \ + node_modules/sinon/pkg/sinon.js \ + node_modules/squirejs/src/Squire.js + +# Run webpack. +# (reimplementing pavelib.assets:webpack) +NODE_ENV=development \ + STATIC_ROOT_LMS=/edx/var/edxapp/staticfiles \ + STATIC_ROOT_CMS=/edx/var/edxapp/staticfiles/studio \ + JS_ENV_EXTRA_CONFIG="{}" \ + $(npm bin)/webpack --config=webpack.dev.config.js + +# Compile SASS for LMS and CMS. +# (reimplementing pavelib.assets:execute_compile_sass) +./manage.py lms compile_sass lms +./manage.py cms compile_sass cms + +# Collect static assets for LMS and CMS. +# (reimplementing pavelib.assets:collect_assets) +./manage.py lms collectstatic --noinput \ + --ignore "fixtures" \ + --ignore "karma_*.js" \ + --ignore "spec" \ + --ignore "spec_helpers" \ + --ignore "spec-helpers" \ + --ignore "xmodule_js" \ + --ignore "geoip" \ + --ignore "sass" +./manage.py cms collectstatic --noinput \ + --ignore "fixtures" \ + --ignore "karma_*.js" \ + --ignore "spec" \ + --ignore "spec_helpers" \ + --ignore "spec-helpers" \ + --ignore "xmodule_js" \ + --ignore "geoip" \ + --ignore "sass"