pulumi-django-azure 1.0.28__py3-none-any.whl → 1.0.59__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.
- pulumi_django_azure/__init__.py +0 -2
- pulumi_django_azure/azure_helper.py +34 -40
- pulumi_django_azure/context_processors.py +42 -0
- pulumi_django_azure/django_deployment.py +153 -244
- pulumi_django_azure/management/commands/fix_cache_control.py +119 -0
- pulumi_django_azure/management/commands/purge_cache.py +10 -2
- pulumi_django_azure/management/commands/purge_cdn.py +10 -4
- pulumi_django_azure/management/commands/test_redis.py +248 -0
- pulumi_django_azure/middleware.py +26 -41
- pulumi_django_azure/settings.py +62 -34
- {pulumi_django_azure-1.0.28.dist-info → pulumi_django_azure-1.0.59.dist-info}/METADATA +251 -278
- pulumi_django_azure-1.0.59.dist-info/RECORD +14 -0
- {pulumi_django_azure-1.0.28.dist-info → pulumi_django_azure-1.0.59.dist-info}/WHEEL +1 -2
- pulumi_django_azure-1.0.28.dist-info/RECORD +0 -12
- pulumi_django_azure-1.0.28.dist-info/top_level.txt +0 -1
pulumi_django_azure/__init__.py
CHANGED
|
@@ -4,21 +4,22 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
import time
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
+
from enum import Enum
|
|
7
8
|
from subprocess import check_output
|
|
8
9
|
|
|
9
10
|
from azure.identity import DefaultAzureCredential
|
|
10
11
|
from azure.mgmt.resource import SubscriptionClient
|
|
11
12
|
from azure.mgmt.resource.subscriptions.models import Subscription
|
|
12
13
|
|
|
13
|
-
_redis_token_cache = None
|
|
14
|
-
_database_token_cache = None
|
|
15
|
-
|
|
16
14
|
logger = logging.getLogger("pulumi_django_azure.azure_helper")
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
# Azure credentials
|
|
20
18
|
AZURE_CREDENTIAL = DefaultAzureCredential()
|
|
21
19
|
|
|
20
|
+
# Buffer for token expiration (5 minutes)
|
|
21
|
+
TOKEN_EXPIRATION_BUFFER = 300
|
|
22
|
+
|
|
22
23
|
# Get the local IP addresses of the machine (only when runnig on Azure)
|
|
23
24
|
if os.environ.get("IS_AZURE_ENVIRONMENT"):
|
|
24
25
|
LOCAL_IP_ADDRESSES = check_output(["hostname", "--all-ip-addresses"]).decode("utf-8").strip().split(" ")
|
|
@@ -26,30 +27,42 @@ else:
|
|
|
26
27
|
LOCAL_IP_ADDRESSES = []
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
class TokenType(Enum):
|
|
31
|
+
DATABASE = "https://ossrdbms-aad.database.windows.net/.default"
|
|
32
|
+
REDIS = "https://redis.azure.com/.default"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _get_azure_token(type: TokenType) -> str:
|
|
30
36
|
"""
|
|
31
|
-
Get a valid
|
|
37
|
+
Get a valid token for the given scope.
|
|
32
38
|
"""
|
|
33
|
-
global
|
|
34
|
-
_database_token_cache = AZURE_CREDENTIAL.get_token("https://ossrdbms-aad.database.windows.net/.default")
|
|
39
|
+
global AZURE_CREDENTIAL
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
token = AZURE_CREDENTIAL.get_token(type.value)
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
if token.expires_on < time.time() + TOKEN_EXPIRATION_BUFFER:
|
|
44
|
+
# We received an expired or nearly expired token from the API. Force a new token by creating a new instance of the credential.
|
|
45
|
+
logger.debug(
|
|
46
|
+
"Received an expired or nearly expired %s token (current time: %s, token expiration: %s)."
|
|
47
|
+
"Creating a new instance of the credential.",
|
|
48
|
+
type.name,
|
|
49
|
+
time.time(),
|
|
50
|
+
token.expires_on,
|
|
51
|
+
)
|
|
39
52
|
|
|
53
|
+
AZURE_CREDENTIAL = DefaultAzureCredential()
|
|
54
|
+
token = AZURE_CREDENTIAL.get_token(type.value)
|
|
40
55
|
|
|
41
|
-
|
|
42
|
-
"""
|
|
43
|
-
Check if the database token will expire in the next treshold seconds.
|
|
44
|
-
"""
|
|
45
|
-
# If the token is not cached, we consider it expired (so a new one will be fetched)
|
|
46
|
-
if _database_token_cache is None:
|
|
47
|
-
return True
|
|
56
|
+
logger.debug("New %s token (try 2): %s", type.name, token)
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
return token.token
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
|
|
61
|
+
def get_db_password() -> str:
|
|
62
|
+
"""
|
|
63
|
+
Get a valid password for the database.
|
|
64
|
+
"""
|
|
65
|
+
return _get_azure_token(TokenType.DATABASE)
|
|
53
66
|
|
|
54
67
|
|
|
55
68
|
@dataclass
|
|
@@ -62,28 +75,9 @@ def get_redis_credentials() -> RedisCredentials:
|
|
|
62
75
|
"""
|
|
63
76
|
Get valid credentials for the Redis cache.
|
|
64
77
|
"""
|
|
65
|
-
|
|
66
|
-
_redis_token_cache = AZURE_CREDENTIAL.get_token("https://redis.azure.com/.default")
|
|
67
|
-
|
|
68
|
-
t = _redis_token_cache.token
|
|
69
|
-
|
|
70
|
-
logger.debug("New Redis token: %s", _redis_token_cache)
|
|
71
|
-
|
|
72
|
-
return RedisCredentials(_extract_username_from_token(t), t)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def redis_token_will_expire(treshold=300) -> bool:
|
|
76
|
-
"""
|
|
77
|
-
Check if the Redis token will expire in the next treshold seconds.
|
|
78
|
-
"""
|
|
79
|
-
# If the token is not cached, we consider it expired (so a new one will be fetched)
|
|
80
|
-
if _redis_token_cache is None:
|
|
81
|
-
return True
|
|
82
|
-
|
|
83
|
-
logger.debug("Redis token expires on: %s", _redis_token_cache.expires_on)
|
|
78
|
+
token = _get_azure_token(TokenType.REDIS)
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
return _redis_token_cache.expires_on - time.time() < treshold
|
|
80
|
+
return RedisCredentials(_extract_username_from_token(token), token)
|
|
87
81
|
|
|
88
82
|
|
|
89
83
|
def get_subscription() -> Subscription:
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
|
|
6
|
+
from django.conf import settings
|
|
7
|
+
|
|
8
|
+
_build_info_cache = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def add_build_info(request):
|
|
12
|
+
if settings.DEBUG:
|
|
13
|
+
# Generate SHA-1 hash from current timestamp
|
|
14
|
+
timestamp = str(datetime.now().timestamp()).encode("utf-8")
|
|
15
|
+
dev_hash = hashlib.sha1(timestamp).hexdigest()
|
|
16
|
+
return {
|
|
17
|
+
"build_info": {
|
|
18
|
+
"commit": dev_hash,
|
|
19
|
+
"date": datetime.now(),
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
global _build_info_cache
|
|
24
|
+
|
|
25
|
+
if _build_info_cache is None:
|
|
26
|
+
path = settings.BASE_DIR / "build-info.json"
|
|
27
|
+
|
|
28
|
+
if os.path.exists(path):
|
|
29
|
+
with open(path) as f:
|
|
30
|
+
build_info = json.load(f)
|
|
31
|
+
|
|
32
|
+
_build_info_cache = {
|
|
33
|
+
"build_info": {
|
|
34
|
+
"commit": build_info["commit"],
|
|
35
|
+
"date": datetime.fromisoformat(build_info["date"]),
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else:
|
|
39
|
+
# No build info available
|
|
40
|
+
_build_info_cache = {}
|
|
41
|
+
|
|
42
|
+
return _build_info_cache
|