Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add status, bundle probes #213

Merged
merged 4 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Loading