Skip to content

Commit 33e649f

Browse files
authored
Bring Azure storage backend classes to this repository (#6433)
Bring Azure storage backend classes to this repository
2 parents 79891bb + 5d75281 commit 33e649f

File tree

7 files changed

+83
-15
lines changed

7 files changed

+83
-15
lines changed

docker-compose.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
# We do not offer support on this file and configuration at this point.
55
# DO NOT USE DOCKER-COMPOSE SETUP FOR PRODUCTION OR CUSTOM INSTALLATION.
66

7-
# GITHUB_TOKEN environment variable is required to build the images
87
version: '3'
98

109
volumes:
@@ -19,8 +18,6 @@ services:
1918
build:
2019
context: .
2120
dockerfile: ${PWD}/docker/Dockerfile
22-
args:
23-
GITHUB_TOKEN: ${GITHUB_TOKEN}
2421

2522
nginx:
2623
image: nginx

docker/Dockerfile

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
FROM ubuntu:18.04
22

3-
ARG GITHUB_TOKEN
4-
53
ENV DEBIAN_FRONTEND noninteractive
64
ENV LANG C.UTF-8
75

@@ -25,18 +23,13 @@ RUN apt-get -y install \
2523
libjpeg-dev \
2624
sqlite
2725

28-
RUN pip3 install --upgrade pip
26+
RUN pip3 install --no-cache-dir --upgrade pip
2927

3028
RUN mkdir checkouts
3129
WORKDIR /usr/src/app/checkouts
3230

3331
COPY requirements readthedocs.org/requirements
3432

35-
RUN pip install --no-cache-dir -r readthedocs.org/requirements/docker.txt
36-
37-
# We clone the -ext here only to install the requirements at this point.
38-
# -ext is also mounted as volume from the upper directory
39-
RUN git clone --single-branch --depth 1 https://${GITHUB_TOKEN}@github.com/readthedocs/readthedocs-ext
40-
RUN pip install --no-cache-dir -e readthedocs-ext
33+
RUN pip3 install --no-cache-dir -r readthedocs.org/requirements/docker.txt
4134

4235
WORKDIR /usr/src/app/checkouts/readthedocs.org

readthedocs/settings/docker_compose.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ def DATABASES(self): # noqa
8989
AZURE_OVERWRITE_FILES = True
9090

9191
# Storage backend for build media artifacts (PDF, HTML, ePub, etc.)
92-
RTD_BUILD_MEDIA_STORAGE = 'readthedocsext.storage.azure_storage.AzureBuildMediaStorage'
92+
RTD_BUILD_MEDIA_STORAGE = 'readthedocs.storage.azure_storage.AzureBuildMediaStorage'
9393
AZURE_STATIC_STORAGE_HOSTNAME = 'community.dev.readthedocs.io'
9494

9595
# Storage for static files (those collected with `collectstatic`)
96-
STATICFILES_STORAGE = 'readthedocsext.storage.azure_storage.AzureStaticStorage'
96+
STATICFILES_STORAGE = 'readthedocs.storage.azure_storage.AzureStaticStorage'
9797

9898
STATICFILES_DIRS = [
9999
os.path.join(CommunityDevSettings.SITE_ROOT, 'readthedocs', 'static'),

readthedocs/storage/__init__.py

Whitespace-only changes.

readthedocs/storage/azure_storage.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# pylint: disable=abstract-method
2+
# Disable: Method 'path' is abstract in class 'Storage' but is not overridden
3+
4+
"""Django storage classes to use with Azure Blob storage service."""
5+
6+
from azure.common import AzureMissingResourceHttpError
7+
from django.conf import settings
8+
from django.contrib.staticfiles.storage import ManifestFilesMixin
9+
from storages.backends.azure_storage import AzureStorage
10+
11+
from readthedocs.builds.storage import BuildMediaStorageMixin
12+
13+
from .mixins import OverrideHostnameMixin
14+
15+
16+
class AzureBuildMediaStorage(BuildMediaStorageMixin, OverrideHostnameMixin, AzureStorage):
17+
18+
"""An Azure Storage backend for build artifacts."""
19+
20+
azure_container = getattr(settings, 'AZURE_MEDIA_STORAGE_CONTAINER', None) or 'media'
21+
override_hostname = getattr(settings, 'AZURE_MEDIA_STORAGE_HOSTNAME', None)
22+
23+
24+
class AzureBuildStorage(AzureStorage):
25+
26+
"""An Azure Storage backend for build cold storage."""
27+
28+
azure_container = getattr(settings, 'AZURE_BUILD_STORAGE_CONTAINER', None) or 'builds'
29+
30+
31+
class AzureStaticStorage(OverrideHostnameMixin, ManifestFilesMixin, AzureStorage):
32+
33+
"""
34+
An Azure Storage backend for static media.
35+
36+
* Uses Django's ManifestFilesMixin to have unique file paths (eg. core.a6f5e2c.css)
37+
"""
38+
39+
azure_container = getattr(settings, 'AZURE_STATIC_STORAGE_CONTAINER', None) or 'static'
40+
override_hostname = getattr(settings, 'AZURE_STATIC_STORAGE_HOSTNAME', None)
41+
42+
def read_manifest(self):
43+
"""Handle a workaround to make Azure work with Django on the first 'collectstatic'."""
44+
try:
45+
return super().read_manifest()
46+
except AzureMissingResourceHttpError:
47+
# Normally Django handles this transparently as long as failing
48+
# to read the manifest throws an IOError. However, failing to
49+
# read a missing file from Azure storage doesn't currently
50+
return None

readthedocs/storage/mixins.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Django storage mixin classes for different storage backends (Azure, S3)."""
2+
3+
from urllib.parse import urlsplit, urlunsplit
4+
5+
6+
class OverrideHostnameMixin:
7+
8+
"""
9+
Override the hostname when outputting URLs.
10+
11+
This is useful for use with a CDN or when proxying outside of Blob Storage
12+
13+
See: https://github.com/jschneier/django-storages/pull/658
14+
"""
15+
16+
override_hostname = None # Just the hostname without scheme (eg. 'assets.readthedocs.org')
17+
18+
def url(self, *args, **kwargs):
19+
url = super().url(*args, **kwargs)
20+
21+
if self.override_hostname:
22+
parts = list(urlsplit(url))
23+
parts[1] = self.override_hostname
24+
url = urlunsplit(parts)
25+
26+
return url

requirements/pip.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ django-cors-middleware==1.4.0
107107
user-agents==2.0
108108

109109
# Utilities used to upload build media to cloud storage
110-
django-storages==1.7.2
110+
django-storages[azure]==1.7.2
111+
azure-storage-blob==1.5.0
112+
azure-storage-common==1.4.2
111113

112114
# Required only in development and linting
113115
django-debug-toolbar==2.0

0 commit comments

Comments
 (0)