|
6 | 6 | import time
|
7 | 7 | import functools
|
8 | 8 | from typing import Dict, List
|
| 9 | +from urllib.parse import urlsplit |
9 | 10 |
|
10 | 11 | from django.conf import settings
|
11 | 12 | from django.db.models import Prefetch
|
@@ -186,23 +187,50 @@ def __init__(self, varnish, input_data):
|
186 | 187 | 'mesh_routing': varnish.cluster.service_mesh_routing
|
187 | 188 | }
|
188 | 189 |
|
| 190 | + def filter_cluster_domain_mappings( |
| 191 | + self, cluster: LogicalCluster |
| 192 | + ) -> dict[str, list[str]]: |
| 193 | + """Returns a dictionary where keys are domains, and values are mapped to by the key""" |
| 194 | + # we can PROBABLY assume that each domain has only one mapping |
| 195 | + # in an experiment trying to add a new mapping for a source domain removed the old one |
| 196 | + destination_dict = {} |
| 197 | + for domain_mapping in self.input.domain_mappings: |
| 198 | + domain = domain_mapping.domain |
| 199 | + destination_dict[domain] = domain_mapping.mapped_domains(cluster) |
| 200 | + return destination_dict |
| 201 | + |
| 202 | + def provide_related_domains(self, cluster: LogicalCluster) -> list[str]: |
| 203 | + """Returns a list of all domains related to a cluster - for static mappings, |
| 204 | + the list is specified within the mapping, for dynamic - clusters are associated using |
| 205 | + labels (mapping targets can contain labels, and each cluster can have multiple labels, but |
| 206 | + each label belongs to exactly one cluster)""" |
| 207 | + result = {m.domain for m in self.input.static_domain_mappings_by_cluster[cluster.name]} |
| 208 | + for m in self.input.mapping_provider.mappings["dynamic"]: |
| 209 | + if m.is_cluster_related_by_labels(cluster): |
| 210 | + result.add(m.domain) |
| 211 | + return sorted(list(result)) |
| 212 | + |
189 | 213 | @collect_processing
|
190 | 214 | def prepare_redirects(self) -> Dict[str, List[VclRedirect]]:
|
191 | 215 | redirects = {}
|
192 |
| - related_domains = MappingProvider(DomainMapping.objects.all()).provide_related_domains(self.varnish.cluster) # tutaj juz mamy dwa zapytania do bazy |
| 216 | + related_domains = self.provide_related_domains(self.varnish.cluster) |
| 217 | + destinations_dict = self.filter_cluster_domain_mappings(self.varnish.cluster) |
193 | 218 | for redirect in self.input.redirects:
|
194 |
| - destination_domain, destination_mappings = redirect.fetch_all_destinations_mappings(self.varnish.cluster) # tutaj znów sięgamy do bazy po redirecty i liste mappingow |
195 |
| - if str(redirect.src_domain) in related_domains: |
196 |
| - for mapped_domain in redirect.src_domain.mapped_domains(self.varnish.cluster): |
197 |
| - destination = str(redirect.destination) |
198 |
| - if destination_domain == redirect.src_domain.domain: |
199 |
| - destination = destination.replace(destination_domain, mapped_domain) |
200 |
| - elif all((destination_domain, len(destination_mappings) == 1)): |
201 |
| - destination = destination.replace(destination_domain, destination_mappings[0]) |
202 |
| - if entries := redirects.get(mapped_domain, []): |
203 |
| - entries.append(VclRedirect(redirect, mapped_domain, destination)) |
204 |
| - else: |
205 |
| - redirects[mapped_domain] = [VclRedirect(redirect, mapped_domain, destination)] |
| 219 | + if str(redirect.src_domain) not in related_domains: |
| 220 | + continue |
| 221 | + destination_domain = urlsplit(redirect.destination).netloc |
| 222 | + destination_mappings = destinations_dict.get(destination_domain) |
| 223 | + for mapped_domain in redirect.src_domain.mapped_domains(self.varnish.cluster): |
| 224 | + destination = str(redirect.destination) |
| 225 | + if destination_domain == redirect.src_domain.domain: |
| 226 | + destination = destination.replace(destination_domain, mapped_domain) |
| 227 | + elif destination_domain and len(destination_mappings) == 1: |
| 228 | + destination = destination.replace(destination_domain, destination_mappings[0]) |
| 229 | + |
| 230 | + if entries := redirects.get(mapped_domain, []): |
| 231 | + entries.append(VclRedirect(redirect, mapped_domain, destination)) |
| 232 | + else: |
| 233 | + redirects[mapped_domain] = [VclRedirect(redirect, mapped_domain, destination)] |
206 | 234 | return redirects
|
207 | 235 |
|
208 | 236 | @collect_processing
|
@@ -392,6 +420,18 @@ def fetch_render_data(self):
|
392 | 420 | )
|
393 | 421 | self.distributed_backends = self.distribute_backends(backends)
|
394 | 422 | self.distributed_canary_backends = self.prepare_canary_backends(canary_backend_ids, backends)
|
| 423 | + self.domain_mappings = DomainMapping.objects.all() |
| 424 | + self.mapping_provider = MappingProvider(self.domain_mappings) |
| 425 | + self.static_domain_mappings_by_cluster = self.cluster_static_domain_mappings() |
| 426 | + |
| 427 | + def cluster_static_domain_mappings(self) -> dict[str, list[DomainMapping]]: |
| 428 | + """Returns a dict cluster.name: [associated domain mappings]""" |
| 429 | + # NTH: get the same output with only one database query, perhaps with prefetch_related() |
| 430 | + result_dict = dict() |
| 431 | + all_clusters = LogicalCluster.objects.all() |
| 432 | + for cluster in all_clusters: |
| 433 | + result_dict[cluster.name] = cluster.domainmapping_set.filter(type="static") |
| 434 | + return result_dict |
395 | 435 |
|
396 | 436 | @collect_processing
|
397 | 437 | def distribute_backends(self, backends):
|
|
0 commit comments