pulumi-django-azure 1.0.10__py3-none-any.whl → 1.0.12__py3-none-any.whl

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.

@@ -95,7 +95,7 @@ class DjangoDeployment(pulumi.ComponentResource):
95
95
  """
96
96
 
97
97
  # Put CDN in front
98
- cdn = azure.cdn.Profile(
98
+ self._cdn_profile = azure.cdn.Profile(
99
99
  f"cdn-{self._name}",
100
100
  resource_group_name=self._rg,
101
101
  location="global",
@@ -125,7 +125,7 @@ class DjangoDeployment(pulumi.ComponentResource):
125
125
  ],
126
126
  is_http_allowed=False,
127
127
  is_https_allowed=True,
128
- profile_name=cdn.name,
128
+ profile_name=self._cdn_profile.name,
129
129
  origin_host_header=endpoint_origin,
130
130
  origins=[azure.cdn.DeepCreatedOriginArgs(name="origin-storage", host_name=endpoint_origin)],
131
131
  query_string_caching_behavior=azure.cdn.QueryStringCachingBehavior.IGNORE_QUERY_STRING,
@@ -138,7 +138,7 @@ class DjangoDeployment(pulumi.ComponentResource):
138
138
  azure.cdn.CustomDomain(
139
139
  f"cdn-custom-domain-{self._name}",
140
140
  resource_group_name=self._rg,
141
- profile_name=cdn.name,
141
+ profile_name=self._cdn_profile.name,
142
142
  endpoint_name=self._cdn_endpoint.name,
143
143
  host_name=custom_host,
144
144
  )
@@ -392,11 +392,19 @@ class DjangoDeployment(pulumi.ComponentResource):
392
392
  return comm_service
393
393
 
394
394
  def _add_webapp_vault(self, administrators: list[str], suffix: str) -> azure.keyvault.Vault:
395
- # Create a keyvault
395
+ # Create a keyvault with a random suffix to make the name unique
396
+ random_suffix = pulumi_random.RandomString(
397
+ f"vault-suffix-{suffix}",
398
+ # Total length is 24, so deduct the length of the suffix
399
+ length=(24 - 7 - len(suffix)),
400
+ special=False,
401
+ upper=False,
402
+ )
403
+
396
404
  vault = azure.keyvault.Vault(
397
405
  f"vault-{suffix}",
398
406
  resource_group_name=self._rg,
399
- vault_name=f"vault-{suffix}",
407
+ vault_name=random_suffix.result.apply(lambda r: f"vault-{suffix}-{r}"),
400
408
  properties=azure.keyvault.VaultPropertiesArgs(
401
409
  tenant_id=self._tenant_id,
402
410
  sku=azure.keyvault.SkuArgs(
@@ -604,6 +612,8 @@ class DjangoDeployment(pulumi.ComponentResource):
604
612
  azure.web.NameValuePairArgs(name="AZURE_STORAGE_CONTAINER_MEDIA", value=media_container.name),
605
613
  # CDN
606
614
  azure.web.NameValuePairArgs(name="CDN_HOST", value=self._cdn_host),
615
+ azure.web.NameValuePairArgs(name="CDN_PROFILE", value=self._cdn_profile.name),
616
+ azure.web.NameValuePairArgs(name="CDN_ENDPOINT", value=self._cdn_endpoint.name),
607
617
  # Database settings
608
618
  azure.web.NameValuePairArgs(name="DB_HOST", value=self._pgsql.fully_qualified_domain_name),
609
619
  azure.web.NameValuePairArgs(name="DB_NAME", value=db.name),
@@ -695,6 +705,22 @@ class DjangoDeployment(pulumi.ComponentResource):
695
705
  scope=comms.id,
696
706
  )
697
707
 
708
+ # Grant the app to purge the CDN endpoint
709
+ cdn_role = self._cdn_endpoint.id.apply(
710
+ lambda scope: azure.authorization.get_role_definition(
711
+ role_definition_id="/426e0c7f-0c7e-4658-b36f-ff54d6c29b45",
712
+ scope=scope,
713
+ )
714
+ )
715
+
716
+ azure.authorization.RoleAssignment(
717
+ f"ra-{name}-cdn",
718
+ principal_id=principal_id,
719
+ principal_type=azure.authorization.PrincipalType.SERVICE_PRINCIPAL,
720
+ role_definition_id=cdn_role.id,
721
+ scope=self._cdn_endpoint.id,
722
+ )
723
+
698
724
  # Create a CORS rules for this website
699
725
  if website_hosts:
700
726
  origins = [f"https://{host}" for host in website_hosts]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pulumi-django-azure
3
- Version: 1.0.10
3
+ Version: 1.0.12
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
@@ -59,9 +59,10 @@ Your Django project should contain a folder `cicd` with these files:
59
59
  ```bash
60
60
  python manage.py migrate
61
61
  python manage.py collectstatic --noinput
62
+ python manage.py purge_cdn
62
63
  gunicorn --timeout 600 --workers $((($NUM_CORES*2)+1)) --chdir $APP_PATH yourapplication.wsgi --access-logfile '-' --error-logfile '-'
63
64
  ```
64
- Be sure to change `yourapplication` in the above.
65
+ Be sure to change `yourapplication` in the above. To see the `purge_cdn` management command we use here, see below.
65
66
  ## Installation
66
67
  This package is published on PyPi, so you can just add pulumi-django-azure to your requirements file.
67
68
 
@@ -256,6 +257,82 @@ Be sure to configure the SSH key that Azure will use on GitLab side. You can obt
256
257
 
257
258
  This would then trigger a redeploy everytime you make a commit to your live branch.
258
259
 
260
+ ## CDN Purging
261
+ We added a management command to Django to purge the CDN cache, and added that to the startup script. Our version is here:
262
+ ```python
263
+ import os
264
+
265
+ from azure.mgmt.cdn import CdnManagementClient
266
+ from azure.mgmt.cdn.models import PurgeParameters
267
+ from django.core.management.base import BaseCommand
268
+
269
+ from core.azure_helper import AZURE_CREDENTIAL, get_subscription_id
270
+
271
+
272
+ class Command(BaseCommand):
273
+ help = "Purges the CDN endpoint"
274
+
275
+ def add_arguments(self, parser):
276
+ parser.add_argument(
277
+ "--wait",
278
+ action="store_true",
279
+ help="Wait for the purge operation to complete",
280
+ )
281
+
282
+ def handle(self, *args, **options):
283
+ # Read environment variables
284
+ resource_group = os.getenv("WEBSITE_RESOURCE_GROUP")
285
+ profile_name = os.getenv("CDN_PROFILE")
286
+ endpoint_name = os.getenv("CDN_ENDPOINT")
287
+ content_paths = ["/*"]
288
+
289
+ # Ensure all required environment variables are set
290
+ if not all([resource_group, profile_name, endpoint_name]):
291
+ self.stderr.write(self.style.ERROR("Missing required environment variables."))
292
+ return
293
+
294
+ # Authenticate with Azure
295
+ cdn_client = CdnManagementClient(AZURE_CREDENTIAL, get_subscription_id())
296
+
297
+ try:
298
+ # Purge the CDN endpoint
299
+ purge_operation = cdn_client.endpoints.begin_purge_content(
300
+ resource_group_name=resource_group,
301
+ profile_name=profile_name,
302
+ endpoint_name=endpoint_name,
303
+ content_file_paths=PurgeParameters(content_paths=content_paths),
304
+ )
305
+
306
+ # Check if the --wait argument was provided
307
+ if options["wait"]:
308
+ purge_operation.result() # Wait for the operation to complete
309
+ self.stdout.write(self.style.SUCCESS("CDN endpoint purge operation completed successfully."))
310
+ else:
311
+ self.stdout.write(self.style.SUCCESS("CDN endpoint purge operation started successfully."))
312
+
313
+ except Exception as e:
314
+ self.stderr.write(self.style.ERROR(f"Error executing CDN endpoint purge command: {e}"))
315
+ ```
316
+
317
+ And our azure_helper:
318
+ ```python
319
+ from azure.identity import DefaultAzureCredential
320
+ from azure.mgmt.resource import SubscriptionClient
321
+
322
+ # Azure credentials
323
+ AZURE_CREDENTIAL = DefaultAzureCredential()
324
+
325
+
326
+ def get_db_password() -> str:
327
+ return AZURE_CREDENTIAL.get_token("https://ossrdbms-aad.database.windows.net/.default").token
328
+
329
+
330
+ def get_subscription_id() -> str:
331
+ subscription_client = SubscriptionClient(AZURE_CREDENTIAL)
332
+ subscriptions = list(subscription_client.subscriptions.list())
333
+ return subscriptions[0].subscription_id
334
+ ```
335
+
259
336
  ## Change requests
260
337
  I created this for internal use but since it took me a while to puzzle all the things together I decided to share it.
261
338
  Therefore this project is not super generic, but tailored to my needs. I am however open to pull or change requests to improve this project or to make it more usable for others.
@@ -0,0 +1,7 @@
1
+ pulumi_django_azure/__init__.py,sha256=tXTvPfr8-Nll5cjMyY9yj_0z_PQ0XAcxihzHRCES-hU,63
2
+ pulumi_django_azure/django_deployment.py,sha256=MBdNH2iEOoNyWY5mxiLy8iUkW514LsG-wNjo4MVZlqY,31479
3
+ pulumi_django_azure-1.0.12.dist-info/LICENSE,sha256=NX2LN3U319Zaac8b7ZgfNOco_nTBbN531X_M_13niSg,1087
4
+ pulumi_django_azure-1.0.12.dist-info/METADATA,sha256=hPKNy_NeqAhvQGJFn-4Zw8AUiWU6pM0jpS9ypjzX2as,13957
5
+ pulumi_django_azure-1.0.12.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ pulumi_django_azure-1.0.12.dist-info/top_level.txt,sha256=MNPRJhq-_G8EMCHRkjdcb_xrqzOkmKogXUGV7Ysz3g0,20
7
+ pulumi_django_azure-1.0.12.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- pulumi_django_azure/__init__.py,sha256=tXTvPfr8-Nll5cjMyY9yj_0z_PQ0XAcxihzHRCES-hU,63
2
- pulumi_django_azure/django_deployment.py,sha256=SgMLoQ2Jwm8anADzrEjVhtfJVAJrYJYFoaOL9bDZngE,30275
3
- pulumi_django_azure-1.0.10.dist-info/LICENSE,sha256=NX2LN3U319Zaac8b7ZgfNOco_nTBbN531X_M_13niSg,1087
4
- pulumi_django_azure-1.0.10.dist-info/METADATA,sha256=rAAqdkW9F0I0OWn7XQA2fHKIpqxmJDQWx39TmH0FEnc,11083
5
- pulumi_django_azure-1.0.10.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- pulumi_django_azure-1.0.10.dist-info/top_level.txt,sha256=MNPRJhq-_G8EMCHRkjdcb_xrqzOkmKogXUGV7Ysz3g0,20
7
- pulumi_django_azure-1.0.10.dist-info/RECORD,,