pulumi-django-azure 1.0.22__tar.gz → 1.0.24__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pulumi-django-azure might be problematic. Click here for more details.

Files changed (18) hide show
  1. {pulumi_django_azure-1.0.22/src/pulumi_django_azure.egg-info → pulumi_django_azure-1.0.24}/PKG-INFO +3 -2
  2. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/pyproject.toml +2 -2
  3. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure/django_deployment.py +6 -0
  4. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure/middleware.py +43 -43
  5. pulumi_django_azure-1.0.24/src/pulumi_django_azure/settings.py +154 -0
  6. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24/src/pulumi_django_azure.egg-info}/PKG-INFO +3 -2
  7. pulumi_django_azure-1.0.22/src/pulumi_django_azure/settings.py +0 -137
  8. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/LICENSE +0 -0
  9. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/README.md +0 -0
  10. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/setup.cfg +0 -0
  11. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure/__init__.py +0 -0
  12. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure/azure_helper.py +0 -0
  13. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure/management/commands/__init__.py +0 -0
  14. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure/management/commands/purge_cdn.py +0 -0
  15. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure.egg-info/SOURCES.txt +0 -0
  16. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure.egg-info/dependency_links.txt +0 -0
  17. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure.egg-info/requires.txt +0 -0
  18. {pulumi_django_azure-1.0.22 → pulumi_django_azure-1.0.24}/src/pulumi_django_azure.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: pulumi-django-azure
3
- Version: 1.0.22
3
+ Version: 1.0.24
4
4
  Summary: Simply deployment of Django on Azure with Pulumi
5
5
  Author-email: Maarten Ureel <maarten@youreal.eu>
6
6
  License: MIT License
@@ -46,6 +46,7 @@ Requires-Dist: pulumi>=3.156.0
46
46
  Requires-Dist: pulumi-azure-native>=2.89.1
47
47
  Requires-Dist: pulumi-random>=4.18.0
48
48
  Requires-Dist: redis[hiredis]<6.0.0,>=5.2.1
49
+ Dynamic: license-file
49
50
 
50
51
  # Pulumi Django Deployment
51
52
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pulumi-django-azure"
7
- version = "1.0.22"
7
+ version = "1.0.24"
8
8
  description = "Simply deployment of Django on Azure with Pulumi"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Maarten Ureel", email = "maarten@youreal.eu" }]
@@ -37,7 +37,7 @@ Homepage = "https://gitlab.com/MaartenUreel/pulumi-django-azure"
37
37
 
38
38
  [tool.poetry]
39
39
  name = "pulumi-django-azure"
40
- version = "1.0.22"
40
+ version = "1.0.24"
41
41
  description = "Simply deployment of Django on Azure with Pulumi"
42
42
  authors = ["Maarten Ureel <maarten@youreal.eu>"]
43
43
 
@@ -844,6 +844,7 @@ class DjangoDeployment(pulumi.ComponentResource):
844
844
  dedicated_app_service_sku: azure.web.SkuDescriptionArgs | None = None,
845
845
  vault_administrators: list[str] | None = None,
846
846
  cache_db: int | None = None,
847
+ startup_timeout: int = 300,
847
848
  ) -> azure.web.WebApp:
848
849
  """
849
850
  Create a Django website with it's own database and storage containers.
@@ -864,6 +865,7 @@ class DjangoDeployment(pulumi.ComponentResource):
864
865
  :param dedicated_app_service_sku: The SKU for the dedicated App Service Plan (optional).
865
866
  :param vault_administrators: The principal IDs of the vault administrators (optional).
866
867
  :param cache_db: The index of the cache database to use (optional).
868
+ :param startup_timeout: The startup timeout for the App Service (default is 300 seconds).
867
869
  """
868
870
 
869
871
  # Create a database
@@ -962,6 +964,10 @@ class DjangoDeployment(pulumi.ComponentResource):
962
964
  # scm_type=azure.web.ScmType.EXTERNAL_GIT,
963
965
  linux_fx_version=f"PYTHON|{python_version}",
964
966
  app_settings=[
967
+ # Startup settings
968
+ azure.web.NameValuePairArgs(name="WEBSITES_CONTAINER_START_TIME_LIMIT", value=str(startup_timeout)),
969
+ # To support our settings helper
970
+ azure.web.NameValuePairArgs(name="IS_AZURE_ENVIRONMENT", value="true"),
965
971
  # Build settings
966
972
  azure.web.NameValuePairArgs(name="SCM_DO_BUILD_DURING_DEPLOYMENT", value="true"),
967
973
  azure.web.NameValuePairArgs(name="PRE_BUILD_COMMAND", value="cicd/pre_build.sh"),
@@ -1,43 +1,43 @@
1
- from django.conf import settings
2
- from django.core.cache import cache
3
- from django.db import connection
4
- from django.db.utils import OperationalError
5
- from django.http import HttpResponse
6
- from django_redis import get_redis_connection
7
-
8
- from .azure_helper import get_db_password, get_redis_credentials
9
-
10
-
11
- class HealthCheckMiddleware:
12
- def __init__(self, get_response):
13
- self.get_response = get_response
14
-
15
- def __call__(self, request):
16
- if request.path == settings.HEALTH_CHECK_PATH:
17
- # Update the database credentials if needed
18
- if settings.AZURE_DB_PASSWORD:
19
- settings.DATABASES["default"]["PASSWORD"] = get_db_password()
20
-
21
- # Update the Redis credentials if needed
22
- if settings.AZURE_REDIS_CREDENTIALS:
23
- redis_credentials = get_redis_credentials()
24
-
25
- # Re-authenticate the Redis connection
26
- redis_connection = get_redis_connection("default")
27
- redis_connection.execute_command("AUTH", redis_credentials.username, redis_credentials.password)
28
-
29
- settings.CACHES["default"]["OPTIONS"]["PASSWORD"] = redis_credentials.password
30
-
31
- try:
32
- # Test the database connection
33
- connection.ensure_connection()
34
-
35
- # Test the Redis connection
36
- cache.set("health_check", "test")
37
-
38
- return HttpResponse("OK")
39
-
40
- except OperationalError:
41
- return HttpResponse(status=503)
42
-
43
- return self.get_response(request)
1
+ from django.conf import settings
2
+ from django.core.cache import cache
3
+ from django.db import connection
4
+ from django.db.utils import OperationalError
5
+ from django.http import HttpResponse
6
+ from django_redis import get_redis_connection
7
+
8
+ from .azure_helper import get_db_password, get_redis_credentials
9
+
10
+
11
+ class HealthCheckMiddleware:
12
+ def __init__(self, get_response):
13
+ self.get_response = get_response
14
+
15
+ def __call__(self, request):
16
+ if request.path == settings.HEALTH_CHECK_PATH:
17
+ # Update the database credentials if needed
18
+ if settings.AZURE_DB_PASSWORD:
19
+ settings.DATABASES["default"]["PASSWORD"] = get_db_password()
20
+
21
+ # Update the Redis credentials if needed
22
+ if settings.AZURE_REDIS_CREDENTIALS:
23
+ redis_credentials = get_redis_credentials()
24
+
25
+ # Re-authenticate the Redis connection
26
+ redis_connection = get_redis_connection("default")
27
+ redis_connection.execute_command("AUTH", redis_credentials.username, redis_credentials.password)
28
+
29
+ settings.CACHES["default"]["OPTIONS"]["PASSWORD"] = redis_credentials.password
30
+
31
+ try:
32
+ # Test the database connection
33
+ connection.ensure_connection()
34
+
35
+ # Test the Redis connection
36
+ cache.set("health_check", "test")
37
+
38
+ return HttpResponse("OK")
39
+
40
+ except OperationalError:
41
+ return HttpResponse(status=503)
42
+
43
+ return self.get_response(request)
@@ -0,0 +1,154 @@
1
+ import environ
2
+ from azure.keyvault.secrets import SecretClient
3
+
4
+ from .azure_helper import AZURE_CREDENTIAL, LOCAL_IP_ADDRESSES, get_db_password, get_redis_credentials, get_subscription
5
+
6
+ env = environ.Env()
7
+
8
+ SECRET_KEY = env("DJANGO_SECRET_KEY", default=None)
9
+
10
+ IS_AZURE_ENVIRONMENT = env("IS_AZURE_ENVIRONMENT", default=False)
11
+
12
+ # Some generic stuff we only need if we're running in Azure.
13
+ # Most of the other stuff will check for the explicit variable we need.
14
+ if IS_AZURE_ENVIRONMENT:
15
+ # Detect HTTPS behind AppService
16
+ SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
17
+
18
+ # Azure context
19
+ AZURE_SUBSCRIPTION = get_subscription()
20
+ AZURE_TENANT_ID = AZURE_SUBSCRIPTION.tenant_id
21
+ AZURE_SUBSCRIPTION_ID = AZURE_SUBSCRIPTION.subscription_id
22
+
23
+ # Health check path
24
+ HEALTH_CHECK_PATH = env("HEALTH_CHECK_PATH", default="/health")
25
+
26
+ ALLOWED_HOSTS: list = env.list("DJANGO_ALLOWED_HOSTS", default=[])
27
+
28
+ # WEBSITE_HOSTNAME contains the Azure domain name
29
+ if website_hostname := env("WEBSITE_HOSTNAME", default=None):
30
+ ALLOWED_HOSTS.append(website_hostname)
31
+
32
+ # Add the local IP addresses of the machine for health checks
33
+ ALLOWED_HOSTS.extend(LOCAL_IP_ADDRESSES)
34
+
35
+ # Azure Key Vault
36
+ if azure_key_vault := env("AZURE_KEY_VAULT", default=None):
37
+ AZURE_KEY_VAULT_URI = f"https://{azure_key_vault}.vault.azure.net"
38
+ AZURE_KEY_VAULT_CLIENT = SecretClient(vault_url=AZURE_KEY_VAULT_URI, credential=AZURE_CREDENTIAL)
39
+
40
+ # Allow CSRF cookies to be sent from our domains
41
+ # CSRF_TRUSTED_ORIGINS = ["https://" + host for host in ALLOWED_HOSTS]
42
+ if azure_storage_account_name := env("AZURE_STORAGE_ACCOUNT_NAME", default=None):
43
+ AZURE_ACCOUNT_NAME = azure_storage_account_name
44
+ AZURE_TOKEN_CREDENTIAL = AZURE_CREDENTIAL
45
+
46
+
47
+ # CDN domain - shared for all storages
48
+ if cdn_host := env("CDN_HOST", default=None):
49
+ AZURE_CUSTOM_DOMAIN = cdn_host
50
+
51
+ STATIC_URL = f"https://{AZURE_CUSTOM_DOMAIN}/static/"
52
+ MEDIA_URL = f"https://{AZURE_CUSTOM_DOMAIN}/media/"
53
+
54
+ # Storage configuration
55
+ STORAGES = {}
56
+ if container_media := env("AZURE_STORAGE_CONTAINER_MEDIA", default=None):
57
+ STORAGES["default"] = {
58
+ "BACKEND": "storages.backends.azure_storage.AzureStorage",
59
+ "OPTIONS": {
60
+ "azure_container": container_media,
61
+ "overwrite_files": False,
62
+ },
63
+ }
64
+
65
+ if container_staticfiles := env("AZURE_STORAGE_CONTAINER_STATICFILES", default=None):
66
+ STORAGES["staticfiles"] = {
67
+ "BACKEND": "storages.backends.azure_storage.AzureStorage",
68
+ "OPTIONS": {
69
+ "azure_container": container_staticfiles,
70
+ },
71
+ }
72
+
73
+ # This setting enables password rotation in the health check middleware
74
+ if IS_AZURE_ENVIRONMENT:
75
+ AZURE_DB_PASSWORD = True
76
+ DATABASES = {
77
+ "default": {
78
+ "ENGINE": "django.db.backends.postgresql",
79
+ "NAME": env("DB_NAME"),
80
+ "USER": env("DB_USER"),
81
+ "HOST": env("DB_HOST"),
82
+ "PASSWORD": get_db_password(),
83
+ "PORT": "5432",
84
+ "OPTIONS": {
85
+ "sslmode": "require",
86
+ },
87
+ # Make connections persistent
88
+ "CONN_MAX_AGE": None,
89
+ # To enable health checks, add the following:
90
+ # "CONN_HEALTH_CHECKS": True,
91
+ }
92
+ }
93
+
94
+ # Email
95
+ EMAIL_BACKEND = "django_azure_communication_email.EmailBackend"
96
+ AZURE_COMMUNICATION_ENDPOINT = env("AZURE_COMMUNICATION_SERVICE_ENDPOINT", default=None)
97
+ DEFAULT_FROM_EMAIL = env("DJANGO_DEFAULT_FROM_EMAIL", default=None)
98
+
99
+
100
+ # Logging
101
+ if IS_AZURE_ENVIRONMENT:
102
+ LOGGING = {
103
+ "version": 1,
104
+ "disable_existing_loggers": False,
105
+ "handlers": {
106
+ "file": {
107
+ "level": "INFO",
108
+ "class": "logging.handlers.TimedRotatingFileHandler",
109
+ "filename": "/home/LogFiles/django.log",
110
+ "when": "h",
111
+ "interval": 1,
112
+ "backupCount": 24,
113
+ },
114
+ },
115
+ "loggers": {
116
+ "django": {
117
+ "handlers": ["file"],
118
+ "level": "INFO",
119
+ "propagate": True,
120
+ },
121
+ },
122
+ }
123
+
124
+ # Redis, if enabled
125
+ redis_cache_host = env("REDIS_CACHE_HOST", default=None)
126
+ redis_cache_port = env("REDIS_CACHE_PORT", default=None)
127
+ redis_cache_db = env("REDIS_CACHE_DB", default=None)
128
+
129
+ if redis_cache_host and redis_cache_port and redis_cache_db:
130
+ # This will enable the health check to update the Redis credentials
131
+ AZURE_REDIS_CREDENTIALS = True
132
+
133
+ # This will prevent the website from failing if Redis is not available
134
+ DJANGO_REDIS_IGNORE_EXCEPTIONS = True
135
+ DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = True
136
+
137
+ REDIS_CACHE_HOST = redis_cache_host
138
+ REDIS_CACHE_PORT = redis_cache_port
139
+ REDIS_CACHE_DB = redis_cache_db
140
+ redis_credentials = get_redis_credentials()
141
+ REDIS_USERNAME = redis_credentials.username
142
+ REDIS_PASSWORD = redis_credentials.password
143
+
144
+ CACHES = {
145
+ "default": {
146
+ "BACKEND": "django_redis.cache.RedisCache",
147
+ "LOCATION": f"rediss://{REDIS_USERNAME}@{REDIS_CACHE_HOST}:{REDIS_CACHE_PORT}/{REDIS_CACHE_DB}",
148
+ "OPTIONS": {
149
+ "CLIENT_CLASS": "django_redis.client.DefaultClient",
150
+ "PARSER_CLASS": "redis.connection._HiredisParser",
151
+ "PASSWORD": REDIS_PASSWORD,
152
+ },
153
+ },
154
+ }
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: pulumi-django-azure
3
- Version: 1.0.22
3
+ Version: 1.0.24
4
4
  Summary: Simply deployment of Django on Azure with Pulumi
5
5
  Author-email: Maarten Ureel <maarten@youreal.eu>
6
6
  License: MIT License
@@ -46,6 +46,7 @@ Requires-Dist: pulumi>=3.156.0
46
46
  Requires-Dist: pulumi-azure-native>=2.89.1
47
47
  Requires-Dist: pulumi-random>=4.18.0
48
48
  Requires-Dist: redis[hiredis]<6.0.0,>=5.2.1
49
+ Dynamic: license-file
49
50
 
50
51
  # Pulumi Django Deployment
51
52
 
@@ -1,137 +0,0 @@
1
- import environ
2
- from azure.keyvault.secrets import SecretClient
3
-
4
- from .azure_helper import AZURE_CREDENTIAL, LOCAL_IP_ADDRESSES, get_db_password, get_redis_credentials, get_subscription
5
-
6
- env = environ.Env()
7
-
8
- SECRET_KEY = env("DJANGO_SECRET_KEY")
9
-
10
- # Health check path
11
- HEALTH_CHECK_PATH = env("HEALTH_CHECK_PATH", default="/health")
12
-
13
- ALLOWED_HOSTS: list = env.list("DJANGO_ALLOWED_HOSTS", default=[])
14
- # WEBSITE_HOSTNAME contains the Azure domain name
15
- ALLOWED_HOSTS.append(env("WEBSITE_HOSTNAME"))
16
- # Add the local IP addresses of the machine for health checks
17
- ALLOWED_HOSTS.extend(LOCAL_IP_ADDRESSES)
18
-
19
- # Detect HTTPS behind AppService
20
- SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
21
-
22
-
23
- # Azure context
24
- AZURE_SUBSCRIPTION = get_subscription()
25
- AZURE_TENANT_ID = AZURE_SUBSCRIPTION.tenant_id
26
- AZURE_SUBSCRIPTION_ID = AZURE_SUBSCRIPTION.subscription_id
27
-
28
- # Azure Key Vault
29
- AZURE_KEY_VAULT = env("AZURE_KEY_VAULT")
30
- AZURE_KEY_VAULT_URI = f"https://{AZURE_KEY_VAULT}.vault.azure.net"
31
- AZURE_KEY_VAULT_CLIENT = SecretClient(vault_url=AZURE_KEY_VAULT_URI, credential=AZURE_CREDENTIAL)
32
-
33
- # Allow CSRF cookies to be sent from our domains
34
- # CSRF_TRUSTED_ORIGINS = ["https://" + host for host in ALLOWED_HOSTS]
35
- AZURE_ACCOUNT_NAME = env("AZURE_STORAGE_ACCOUNT_NAME")
36
- AZURE_TOKEN_CREDENTIAL = AZURE_CREDENTIAL
37
-
38
-
39
- # CDN domain - shared for all storages
40
- AZURE_CUSTOM_DOMAIN = env("CDN_HOST")
41
-
42
- STORAGES = {
43
- "default": {
44
- "BACKEND": "storages.backends.azure_storage.AzureStorage",
45
- "OPTIONS": {
46
- "azure_container": env("AZURE_STORAGE_CONTAINER_MEDIA"),
47
- "overwrite_files": False,
48
- },
49
- },
50
- "staticfiles": {
51
- "BACKEND": "storages.backends.azure_storage.AzureStorage",
52
- "OPTIONS": {
53
- "azure_container": env("AZURE_STORAGE_CONTAINER_STATICFILES"),
54
- },
55
- },
56
- }
57
-
58
-
59
- # STATIC_ROOT = BASE_DIR / "staticfiles"
60
- STATIC_URL = f"https://{AZURE_CUSTOM_DOMAIN}/static/"
61
- MEDIA_URL = f"https://{AZURE_CUSTOM_DOMAIN}/media/"
62
-
63
- # This setting enables password rotation in the health check middleware
64
- AZURE_DB_PASSWORD = True
65
- DATABASES = {
66
- "default": {
67
- "ENGINE": "django.db.backends.postgresql",
68
- "NAME": env("DB_NAME"),
69
- "USER": env("DB_USER"),
70
- "HOST": env("DB_HOST"),
71
- "PASSWORD": get_db_password(),
72
- "PORT": "5432",
73
- "OPTIONS": {
74
- "sslmode": "require",
75
- },
76
- # Make connections persistent
77
- "CONN_MAX_AGE": None,
78
- # To enable health checks, add the following:
79
- # "CONN_HEALTH_CHECKS": True,
80
- }
81
- }
82
-
83
- # Email
84
- EMAIL_BACKEND = "django_azure_communication_email.EmailBackend"
85
- AZURE_COMMUNICATION_ENDPOINT = env("AZURE_COMMUNICATION_SERVICE_ENDPOINT")
86
- DEFAULT_FROM_EMAIL = env("DJANGO_DEFAULT_FROM_EMAIL")
87
-
88
-
89
- # Logging
90
- LOGGING = {
91
- "version": 1,
92
- "disable_existing_loggers": False,
93
- "handlers": {
94
- "file": {
95
- "level": "INFO",
96
- "class": "logging.handlers.RotatingFileHandler",
97
- "filename": "/home/LogFiles/django.log",
98
- "maxBytes": 1024 * 1024 * 100, # 100 mb
99
- "backupCount": 5,
100
- },
101
- },
102
- "loggers": {
103
- "django": {
104
- "handlers": ["file"],
105
- "level": "INFO",
106
- "propagate": True,
107
- },
108
- },
109
- }
110
-
111
- # Redis, if enabled
112
- if env("REDIS_CACHE_HOST") and env("REDIS_CACHE_PORT") and env("REDIS_CACHE_DB"):
113
- # This will enable the health check to update the Redis credentials
114
- AZURE_REDIS_CREDENTIALS = True
115
-
116
- # This will prevent the website from failing if Redis is not available
117
- DJANGO_REDIS_IGNORE_EXCEPTIONS = True
118
- DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = True
119
-
120
- REDIS_CACHE_HOST = env("REDIS_CACHE_HOST")
121
- REDIS_CACHE_PORT = env("REDIS_CACHE_PORT")
122
- REDIS_CACHE_DB = env("REDIS_CACHE_DB")
123
- redis_credentials = get_redis_credentials()
124
- REDIS_USERNAME = redis_credentials.username
125
- REDIS_PASSWORD = redis_credentials.password
126
-
127
- CACHES = {
128
- "default": {
129
- "BACKEND": "django_redis.cache.RedisCache",
130
- "LOCATION": f"rediss://{REDIS_USERNAME}@{REDIS_CACHE_HOST}:{REDIS_CACHE_PORT}/{REDIS_CACHE_DB}",
131
- "OPTIONS": {
132
- "CLIENT_CLASS": "django_redis.client.DefaultClient",
133
- "PARSER_CLASS": "redis.connection._HiredisParser",
134
- "PASSWORD": REDIS_PASSWORD,
135
- },
136
- },
137
- }