Skip to content

Commit

Permalink
Add status, bundle probes (#213)
Browse files Browse the repository at this point in the history
Add probes for type: status, bundle
  • Loading branch information
sed-i authored Jan 24, 2025
1 parent ae09f33 commit 11eab4d
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 0 deletions.
15 changes: 15 additions & 0 deletions probes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# External probes

These probes are meant to be run from the host where the juju client is installed,

```bash
juju export-bundle | ./bundle/probe_bundle.py
juju status --format=yaml | ./status/probe_status.py
```

or by piping in the bundle yaml,

```bash
cat bundle.yaml | ./bundle/probe_bundle.py
cat status.yaml | ./status/probe_status.py
```
67 changes: 67 additions & 0 deletions probes/bundle/probe_bundle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env python3

import sys
import yaml
from itertools import combinations
from collections import defaultdict


def one_grafana_agent_per_machine(bundle: dict):
applications = bundle["applications"]
relations = bundle["relations"]

# A mapping from app name to the machines it is deployed on
principals_to_machines = {k: set(v["to"]) for k, v in applications.items() if "to" in v}

# List of grafana-agent app names
grafana_agent_names = [k for k, v in applications.items() if v["charm"] == "grafana-agent"]

principals_related_to_grafana_agent = []
subordinates_related_to_grafana_agent = []
for rel_pair in relations:
# Truncate the relation names
apps_pair = [s.split(':',-1)[0] for s in rel_pair]

related_app = None
if apps_pair[0] in grafana_agent_names:
related_app = apps_pair[1]
elif apps_pair[1] in grafana_agent_names:
related_app = apps_pair[0]

if related_app:
if related_app in principals_to_machines:
principals_related_to_grafana_agent.append(related_app)
elif related_app in applications:
subordinates_related_to_grafana_agent.append(related_app)

for app1,app2 in combinations(principals_related_to_grafana_agent, 2):
if isect := principals_to_machines[app1].intersection(principals_to_machines[app2]):
print(f"grafana-agent is related to '{app1}', '{app2}' on the same machine(s) {isect}")


def one_grafana_agent_per_app(bundle: dict):
applications = bundle["applications"]
relations = bundle["relations"]

# List of grafana-agent app names
grafana_agent_names = [k for k, v in applications.items() if v["charm"] == "grafana-agent"]

counter = defaultdict(list)
for rel_pair in relations:
# Truncate the relation names
apps_pair = [s.split(':',-1)[0] for s in rel_pair]

if apps_pair[0] in grafana_agent_names and apps_pair[1] in applications:
counter[apps_pair[1]].append(apps_pair[0])
elif apps_pair[1] in grafana_agent_names and apps_pair[0] in applications:
counter[apps_pair[0]].append(apps_pair[1])

for k, v in counter.items():
if len(v) > 1:
print(f"App '{k}' related to multiple grafana-agent apps '{v}'")

if __name__ == '__main__':
bundle = yaml.safe_load(sys.stdin.read())
one_grafana_agent_per_machine(bundle)
one_grafana_agent_per_app(bundle)

53 changes: 53 additions & 0 deletions probes/status/probe_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python3

import sys
import yaml


def one_grafana_agent_per_machine(status: dict):
# A mapping from grafana-agent app name to the list of apps it's subordinate to
agents = {
k: v["subordinate-to"]
for k, v in status["applications"].items()
if v["charm"] == "grafana-agent"
}

for agent, principals in agents.items():
# A mapping from app name to machines
machines = {
p: [u["machine"] for u in status["applications"][p].get("units", {}).values()]
for p in principals
}

from itertools import combinations

for p1, p2 in combinations(principals, 2):
if overlap := set(machines[p1]) & set(machines[p2]):
print(
f"{agent} is subordinate to both '{p1}', '{p2}' in the same machines {overlap}"
)


def one_grafana_agent_per_app(status: dict):
# A mapping from grafana-agent app name to the list of apps it's subordinate to
agents = {
k: v["subordinate-to"]
for k, v in status["applications"].items()
if v["charm"] == "grafana-agent"
}

for agent, principals in agents.items():
for p in principals:
for name, unit in status["applications"][p].get("units", {}).items():
subord_apps = {u.split("/", -1)[0] for u in unit["subordinates"].keys()}
subord_agents = subord_apps & agents.keys()
if len(subord_agents) > 1:
print(
f"{name} is related to more than one grafana-agent subordinate: {subord_agents}"
)


if __name__ == '__main__':
status = yaml.safe_load(sys.stdin.read())
one_grafana_agent_per_machine(status)
one_grafana_agent_per_app(status)

0 comments on commit 11eab4d

Please sign in to comment.