Skip to content
This repository was archived by the owner on Feb 21, 2022. It is now read-only.

Commit 4065b48

Browse files
paveldedikaexvir
authored andcommitted
feat(datacenters): Display mapped infra info on service detail page
Refs: #250
1 parent f8fcffd commit 4065b48

File tree

7 files changed

+185
-9
lines changed

7 files changed

+185
-9
lines changed

zoo/datacenters/mapping.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.db import transaction
55

66
from . import amazon, gcp, models, rancher
7-
from .models import InfraNode, NodeKind
7+
from .models import Datacenter, InfraNode, NodeKind
88
from .utils import GCPClient, KubernetesClient
99

1010

@@ -108,7 +108,7 @@ def _get_gcp_datacenter(self, cluster, service):
108108
_, _, zone, _ = cluster.value.split("_")
109109

110110
datacenter, _ = models.Datacenter.objects.get_or_create(
111-
provider="GCP", region=zone
111+
provider=Datacenter.PROVIDER_GCP, region=zone
112112
)
113113
service_datacenter, _ = models.ServiceDatacenter.objects.get_or_create(
114114
service=service, datacenter=datacenter
@@ -128,12 +128,14 @@ def link_image_to_service(self, image_node, service):
128128
for member in project_members:
129129
models.ServiceDatacenterMember.objects.get_or_create(
130130
service_datacenter=datacenter,
131-
name=member,
132-
email=member.split(":", 1)[1],
131+
name=member["name"],
132+
email=member["email"],
133133
)
134134
models.ServiceDatacenterMember.objects.filter(
135135
service_datacenter=datacenter
136-
).exclude(name__in=project_members).delete()
136+
).exclude(
137+
name__in={member["name"] for member in project_members}
138+
).delete()
137139

138140
for workload in image_node.find_sources_by_kind(NodeKind.GCP_WORKLOAD_NAME):
139141
component_data = self._get_ingress_component(workload)
@@ -200,7 +202,7 @@ def _get_amazon_datacenters(self, component_node, service):
200202
_, zone, _ = elb_node.value.split(".", 2)
201203

202204
datacenter, _ = models.Datacenter.objects.get_or_create(
203-
provider="Amazon", region=zone
205+
provider=Datacenter.PROVIDER_AWS, region=zone
204206
)
205207
service_datacenter, _ = models.ServiceDatacenter.objects.get_or_create(
206208
service=service, datacenter=datacenter
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Generated by Django 2.2.7 on 2019-12-05 10:08
2+
3+
from django.db import migrations
4+
5+
6+
def rename_amazon_to_aws(apps, schema_editor):
7+
Datacenter = apps.get_model("datacenters", "Datacenter")
8+
9+
for datacenter in Datacenter.objects.all():
10+
if datacenter.provider == "Amazon":
11+
datacenter.provider = "AWS"
12+
datacenter.save()
13+
14+
15+
def rename_aws_to_amazon(apps, schema_editor):
16+
Datacenter = apps.get_model("datacenters", "Datacenter")
17+
18+
for datacenter in Datacenter.objects.all():
19+
if datacenter.provider == "AWS":
20+
datacenter.provider = "Amazon"
21+
datacenter.save()
22+
23+
24+
class Migration(migrations.Migration):
25+
26+
dependencies = [
27+
("datacenters", "0002_auto_20191101_1019"),
28+
]
29+
30+
operations = [
31+
migrations.RunPython(rename_amazon_to_aws, reverse_code=rename_aws_to_amazon),
32+
]

zoo/datacenters/models.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from django.contrib.postgres import fields as pg_fields
33
from django.db import models
44

5+
from .templates import get_datacenter_template_data
6+
57

68
def utcnow():
79
return arrow.utcnow().datetime
@@ -59,7 +61,7 @@ def find_sources_by_kind(self, kind):
5961
visited.add(source.id)
6062
if source.kind == kind:
6163
sources_of_kind.append(source)
62-
sources += list(source.sources.all())
64+
sources.extend(source.sources.all())
6365

6466
return sources_of_kind
6567

@@ -74,12 +76,15 @@ def get_or_create_node(cls, kind, value, source=None):
7476

7577

7678
class Datacenter(models.Model):
77-
class Meta:
78-
unique_together = ("provider", "region")
79+
PROVIDER_GCP = "GCP"
80+
PROVIDER_AWS = "AWS"
7981

8082
provider = models.CharField(max_length=100)
8183
region = models.CharField(max_length=100, null=True, blank=True)
8284

85+
class Meta:
86+
unique_together = ("provider", "region")
87+
8388
def __str__(self):
8489
return f"{self.provider} {self.region}" if self.region else self.provider
8590

@@ -90,6 +95,10 @@ class ServiceDatacenter(models.Model):
9095
)
9196
datacenter = models.ForeignKey("Datacenter", on_delete=models.PROTECT)
9297

98+
@property
99+
def template_metadata(self):
100+
return get_datacenter_template_data(self)
101+
93102
class Meta:
94103
unique_together = ("service", "datacenter")
95104

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
def get_datacenter_template_data(service_datacenter):
2+
datacenter = service_datacenter.datacenter
3+
provider = datacenter.provider
4+
5+
component_labels = {}
6+
members_labels = {}
7+
provider_icons = {
8+
datacenter.PROVIDER_GCP: "cog",
9+
datacenter.PROVIDER_AWS: "cog",
10+
}
11+
platform = {
12+
datacenter.PROVIDER_GCP: "kubernetes",
13+
datacenter.PROVIDER_AWS: "rancher",
14+
}
15+
16+
return {
17+
"provider": provider,
18+
"provider_icon": provider_icons.get(provider, "server"),
19+
"platform": platform.get(provider, provider),
20+
"region": datacenter.region,
21+
"components": service_datacenter.components.all(),
22+
"components_label": component_labels.get(provider, "Components"),
23+
"members": service_datacenter.members.all(),
24+
"members_label": members_labels.get(provider, "Members"),
25+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<div class="ui stackable grid tab" data-tab="infrastructure">
2+
{% for datacenter in datacenters %}
3+
{% with metadata=datacenter.template_metadata %}
4+
<div class="ui segment">
5+
<div class="flex-horizontal--space-between">
6+
<h3 class="ui marginless header display-flex">
7+
{% if metadata.platform == "kubernetes" %}
8+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="9.7 9.4 210.6 204.6" class="ui marginless icon" aria-hidden="true" height="24">
9+
<path d="M134.4 126.5a3.6 3.6 0 00-.9-.1 3.7 3.7 0 00-1.4.4 3.7 3.7 0 00-1.8 4.8l8.5 20.6a43.5 43.5 0 0017.6-22l-22-3.8zm-34.2 2.9a3.7 3.7 0 00-3.6-3 3.7 3.7 0 00-.7.2L74 130.1a43.7 43.7 0 0017.6 22l8.4-20.4v-.1a3.7 3.7 0 00.2-2.3zm18.2 8a3.7 3.7 0 00-6.5 0L101 156.8A43.6 43.6 0 00125 158q2.2-.5 4.3-1.2l-10.7-19.4zm34-45L135.7 107a3.7 3.7 0 001.5 6.5l21.4 6.2a44.3 44.3 0 00-6.4-27.4zM121.6 94a3.7 3.7 0 006 2.9l18-12.8A43.9 43.9 0 00120.4 72l1.3 22.1zm-19.1 3a3.7 3.7 0 005.9-2.9h.1l1.2-22.2a44.7 44.7 0 00-4.5.8 43.5 43.5 0 00-20.9 11.4L102.6 97zm-9.7 16.7a3.7 3.7 0 001.5-6.4l-16.6-15a43.5 43.5 0 00-6.1 27.6l21.2-6.1zm16.1 6.5l6.1 3 6.1-3 1.5-6.6-4.2-5.3h-6.8l-4.2 5.3z"/>
10+
<path d="M216.2 133.2l-17.4-75.7a13.6 13.6 0 00-7.3-9L121 14.6a13.6 13.6 0 00-11.7 0L38.8 48.4a13.6 13.6 0 00-7.3 9.1L14 133.2a13.3 13.3 0 000 5.8 13.5 13.5 0 00.5 1.7 13.1 13.1 0 001.3 2.7l.8 1.1 48.8 60.7.7.7a13.4 13.4 0 002.5 2.2 14 14 0 003.9 1.6 13.3 13.3 0 003.4.5h78.3a13 13 0 001.4 0 13.5 13.5 0 002-.5 13.9 13.9 0 001.4-.4l1-.4a14 14 0 001.5-.9 13.3 13.3 0 003.2-2.8l1.5-1.9 47.3-58.8a13.2 13.2 0 002.1-3.8 13.7 13.7 0 00.5-1.7 13.3 13.3 0 000-5.8zm-73.1 29.4a14.5 14.5 0 00.7 1.7 3.3 3.3 0 00-.4 2.5 39.4 39.4 0 003.8 6.7 35 35 0 012.2 3.4l.6 1a4.2 4.2 0 11-7.6 3.7l-.6-1a35.3 35.3 0 01-1.2-4 39.3 39.3 0 00-2.9-7 3.3 3.3 0 00-2.1-1.4l-1-1.6a54.6 54.6 0 01-38.9 0l-1 1.7a3.4 3.4 0 00-1.8.8 29.5 29.5 0 00-3.2 7.6 34.9 34.9 0 01-1.2 3.9l-.6 1a4.2 4.2 0 11-7.6-3.5l.5-1.2a35.2 35.2 0 012.3-3.3 41.2 41.2 0 003.8-7 4.2 4.2 0 00-.3-2.3l.7-1.8A55 55 0 0163 132l-1.9.3a4.7 4.7 0 00-2.4-.9 39.5 39.5 0 00-7.3 2.2 35.6 35.6 0 01-3.8 1.4l-1.1.3h-.1a4.2 4.2 0 11-2-8.2h.1l1.2-.3a35.3 35.3 0 014-.3 39.4 39.4 0 007.6-1.3 5.8 5.8 0 001.8-1.8l1.8-.5a54.6 54.6 0 018.6-38l-1.4-1.3a4.7 4.7 0 00-.8-2.4 39.4 39.4 0 00-6.3-4.4 35.3 35.3 0 01-3.5-2l-.9-.8a4.5 4.5 0 01-1-6.2 4 4 0 013.3-1.5 5 5 0 013 1l.9.8a35.3 35.3 0 012.8 3 39.4 39.4 0 005.7 5.1 3.3 3.3 0 002.5.3l1.5 1A54.3 54.3 0 01102.9 62a55 55 0 017.6-1.2V59a4.6 4.6 0 001.5-2.2 39.5 39.5 0 00-.5-7.6 35.5 35.5 0 01-.6-4V44v-.1a4.2 4.2 0 118.5 0V45a35.1 35.1 0 01-.6 4 39.5 39.5 0 00-.5 7.6 3.3 3.3 0 001.4 2.2v1.8a55.3 55.3 0 0135.1 17l1.6-1.2a4.7 4.7 0 002.6-.3 39.5 39.5 0 005.7-5.1 35 35 0 012.8-3l.9-.7a4.2 4.2 0 115.3 6.6l-1 .7a35.1 35.1 0 01-3.5 2 39.5 39.5 0 00-6.3 4.5 3.3 3.3 0 00-.7 2.4l-1.5 1.3a54.8 54.8 0 018.7 38l1.8.5a4.7 4.7 0 001.8 1.8 39.5 39.5 0 007.5 1.3 35.6 35.6 0 014 .3l1.3.3a4.2 4.2 0 11-1.9 8.2h-.1l-1.1-.2a35.1 35.1 0 01-3.8-1.5 39.5 39.5 0 00-7.3-2.2 3.3 3.3 0 00-2.4 1l-1.8-.4a55 55 0 01-24.3 30.6z"/>
11+
</svg>
12+
{% elif metadata.platform == "rancher" %}
13+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60.493 28.416" class="ui marginless icon" aria-hidden="true" version="1.1" width="32">
14+
<g transform="translate(-79.201 -162.595)" id="layer1">
15+
<g transform="matrix(.26458 0 0 .26458 79.073 162.595)" id="g3725" fill="#000">
16+
<path id="path3715" d="M229 23.6l-2.5-14.9c-.8-4.8-2.7-8.7-4.1-8.7-1.5 0-2.7 4-2.7 8.8v3.9c0 4.8-4 8.8-8.8 8.8h-4.7v10.7h15.5c4.8 0 8.1-3.9 7.3-8.6" class="st0" fill="#000"/>
17+
<path id="path3717" d="M193.9 11h-48.7c-.3 0-.6 0-.8.1V8.8c0-4.8-1.2-8.8-2.7-8.8-1.5 0-3.3 3.9-4.1 8.7l-2.5 14.9c-.8 4.8 2.5 8.7 7.4 8.7h14.6c1.5 0 2.9-.2 4.2-.6-.5 2.5-2.6 4.4-5.3 4.4h-20.5c-3.3 0-5.8-3-5.3-6.3l2.1-12.5c.5-3.3-2-6.3-5.3-6.3H24.8c-2.2 0-4 1.3-4.9 3.2L.7 43.5c-.3.5-.3 1.1.1 1.6l3.7 4.4c.5.6 1.3.6 1.9.2l13.1-10.3V102c0 3 2.4 5.4 5.4 5.4h29c3 0 5.4-2.4 5.4-5.4V80.2c0-3 2.4-5.4 5.4-5.4h72.4c3 0 5.4 2.4 5.4 5.4V102c0 3 2.4 5.4 5.4 5.4h29c3 0 5.4-2.4 5.4-5.4V78.6h-15.4c-4.8 0-8.8-4-8.8-8.8V54.7c0-2.9 1.4-5.4 3.5-7v18c0 4.8 4 8.8 8.8 8.8h23.7c4.8 0 8.8-4 8.8-8.8V19.9c-.2-5-4.1-8.9-9-8.9" class="st0" fill="#000"/>
18+
</g>
19+
</g>
20+
<style type="text/css" id="style3713">.st0{fill:#000}</style>
21+
</svg>
22+
{% else %}
23+
<i class="cog icon"></i>
24+
{% endif %}
25+
26+
<div class="content">
27+
{{ metadata.platform.title }}
28+
</div>
29+
</h3>
30+
<div>
31+
<div class="ui blue large circular regular-font label">region:<b>{{ metadata.region }}</b></div>
32+
</div>
33+
</div>
34+
{% if metadata.members %}
35+
<table class="ui celled striped table">
36+
<thead>
37+
<tr>
38+
<th colspan="3">
39+
<h4 class="ui grey header">
40+
<i class="users icon"></i>
41+
{{ metadata.members_label }}
42+
</h4>
43+
</th>
44+
</tr>
45+
</thead>
46+
<tbody>
47+
{% for member in metadata.members %}
48+
<tr>
49+
<td class="four wide">
50+
{{ member.name }}
51+
</td>
52+
{% if member.email %}
53+
<td>
54+
<i class="envelope icon"></i> {{ member.email }}
55+
</td>
56+
{% endif %}
57+
</tr>
58+
{% endfor %}
59+
</tbody>
60+
</table>
61+
{% endif %}
62+
{% if metadata.components %}
63+
<table class="ui celled striped table">
64+
<thead>
65+
<tr>
66+
<th colspan="3">
67+
<h4 class="ui grey header">
68+
<i class="sitemap icon"></i>
69+
{{ metadata.components_label }}
70+
</h4>
71+
</th>
72+
</tr>
73+
</thead>
74+
<tbody>
75+
{% for component in metadata.components %}
76+
<tr>
77+
<td class="four wide">
78+
{{ component.name }}
79+
</td>
80+
{% if component.urls %}
81+
<td>
82+
{% for url in component.urls %}
83+
<i class="external alternate icon"></i>
84+
<a href="{{ url }}">{{ url }}</a>
85+
{% if not forloop.last %}<br>{% endif %}
86+
{% endfor %}
87+
</td>
88+
{% endif %}
89+
</tr>
90+
{% endfor %}
91+
</tbody>
92+
</table>
93+
{% endif %}
94+
</div>
95+
{% endwith %}
96+
{% endfor %}
97+
</div>

zoo/datacenters/utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from .gcloud import GCPClient
22
from .kube import KubernetesClient
3+
from .misc import email_to_full_name

zoo/services/templates/services/service_detail.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
API
3333
</a>
3434
{% endif %}
35+
{% if object.datacenters.count %}
36+
<a class="item" data-tab="infrastructure">
37+
<i class="server icon"></i>
38+
Infrastructure
39+
</a>
40+
{% endif %}
3541
{% if environment.service_urls %}
3642
<a class="item" href="{{ environment.service_urls.0 }}" target="_blank" rel="noopener noreferrer" style="color: #4183c4;">
3743
<i class="globe americas icon"></i>
@@ -229,6 +235,10 @@ <h3 class="ui marginless api header">
229235
</div>
230236
{% endverbatim %}
231237
{% endif %}
238+
239+
{% if object.datacenters.count %}
240+
{% include "datacenters/infra_overview.html" with datacenters=object.datacenters.all only %}
241+
{% endif %}
232242
{% endblock %}
233243

234244
{% block scripts %}

0 commit comments

Comments
 (0)