Skip to content
This repository was archived by the owner on Oct 3, 2020. It is now read-only.

Commit daaca7f

Browse files
authored
Ingress application (#80)
* find application via ingress backend/service * doc string
1 parent d599642 commit daaca7f

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

deploy/rbac.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ metadata:
1010
name: kube-resource-report
1111
rules:
1212
- apiGroups: [""]
13-
resources: ["nodes", "pods", "namespaces"]
13+
resources: ["nodes", "pods", "namespaces", "services"]
1414
verbs:
15+
- get
1516
- list
1617
- apiGroups: ["extensions"]
1718
resources: ["ingresses"]

kube_resource_report/report.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from jinja2 import Environment, FileSystemLoader, select_autoescape
2020

2121
import pykube
22-
from pykube import Namespace, Pod, Node, Ingress
22+
from pykube import Namespace, Pod, Node, Ingress, Service, ObjectDoesNotExist
2323
from pykube.objects import APIObject, NamespacedAPIObject
2424

2525
from kube_resource_report import cluster_discovery, pricing, filters, __version__
@@ -161,6 +161,38 @@ def get_pod_usage(cluster, pods: dict):
161161
logger.exception("Failed to get pod usage metrics")
162162

163163

164+
def find_backend_application(client, ingress, rule):
165+
'''
166+
The Ingress object might not have a "application" label, so let's try to find the application by looking at the backend service and its pods
167+
'''
168+
paths = rule.get('http', {}).get('paths', [])
169+
selectors = []
170+
for path in paths:
171+
service_name = path.get('backend', {}).get('serviceName')
172+
if service_name:
173+
try:
174+
service = Service.objects(client, namespace=ingress.namespace).get(name=service_name)
175+
except ObjectDoesNotExist:
176+
logger.debug(f'Referenced service does not exist: {ingress.namespace}/{service_name}')
177+
else:
178+
selector = service.obj['spec'].get('selector', {})
179+
selectors.append(selector)
180+
application = get_application_from_labels(selector)
181+
if application:
182+
return application
183+
# we still haven't found the application, let's look up pods by label selectors
184+
for selector in selectors:
185+
application_candidates = set()
186+
for pod in Pod.objects(client).filter(namespace=ingress.namespace, selector=selector):
187+
application = get_application_from_labels(pod.labels)
188+
if application:
189+
application_candidates.add(application)
190+
191+
if len(application_candidates) == 1:
192+
return application_candidates.pop()
193+
return ''
194+
195+
164196
def query_cluster(
165197
cluster, executor, system_namespaces, additional_cost_per_cluster, no_ingress_status, node_label
166198
):
@@ -308,7 +340,12 @@ def query_cluster(
308340
application = get_application_from_labels(_ingress.labels)
309341
for rule in _ingress.obj["spec"].get("rules", []):
310342
host = rule.get('host', '')
311-
ingress = [_ingress.namespace, _ingress.name, application, host, 0]
343+
if not application:
344+
# find the application by getting labels from pods
345+
backend_application = find_backend_application(cluster.client, _ingress, rule)
346+
else:
347+
backend_application = None
348+
ingress = [_ingress.namespace, _ingress.name, application or backend_application, host, 0]
312349
if host and not no_ingress_status:
313350
try:
314351
future = futures_by_host[host]

0 commit comments

Comments
 (0)