Skip to content

Commit

Permalink
Added OS filtering doc and supported (1 level deep) nested definition.
Browse files Browse the repository at this point in the history
  • Loading branch information
DaanSelen committed Feb 13, 2025
1 parent 9494aa1 commit ab1105b
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 18 deletions.
65 changes: 65 additions & 0 deletions docs/operating_system_filtering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# **Understanding the OS Filtering Mechanism**

## **Overview**
This function filters devices based on their **reachability** and an optional **OS category filter**. It supports:

- **Broad OS categories** (e.g., `"Linux"` includes all OS versions under `"Linux"`)
- **Specific OS categories** (e.g., `"Debian"` only includes OS versions under `"Linux" -> "Debian"`)
- **Single category selection** (Only `target_os="Linux"` OR `target_os="Debian"` is used, never both at once)

---

## **How It Works (Simplified)**

### **1. OS Category Expansion**
The function first expands the `target_os` category by retrieving all valid OS names under it.

#### **Example OS Category Structure:**
```json
{
"Linux": {
"Debian": [
"Debian GNU/Linux 12 (bookworm)",
"Debian GNU/Linux 11 (bullseye)"
],
"Ubuntu": [
"Ubuntu 24.04.1 LTS"
]
}
}
```

#### **Expanding Different `target_os` Values:**

| `target_os` | Expanded OS Versions |
|--------------|---------------------------------------------------|
| `"Linux"` | `{ "Debian GNU/Linux 12 (bookworm)", "Debian GNU/Linux 11 (bullseye)", "Ubuntu 24.04.1 LTS" }` |
| `"Debian"` | `{ "Debian GNU/Linux 12 (bookworm)", "Debian GNU/Linux 11 (bullseye)" }` |

---

### **2. Device Filtering**
Once the function has the allowed OS versions, it checks each device:

#### **Example Device List:**
```json
[
{"device_id": "A1", "device_os": "Debian GNU/Linux 12 (bookworm)", "reachable": true},
{"device_id": "A2", "device_os": "Ubuntu 24.04.1 LTS", "reachable": true},
{"device_id": "A3", "device_os": "Windows 11", "reachable": true},
{"device_id": "A4", "device_os": "Debian GNU/Linux 11 (bullseye)", "reachable": false}
]
```

#### **Filtering Behavior:**
| Device ID | Device OS | Reachable | Matches `target_os="Linux"` | Matches `target_os="Debian"` |
|-----------|----------------------------------|-----------|-------------------------------|-------------------------------|
| A1 | Debian GNU/Linux 12 (bookworm) ||||
| A2 | Ubuntu 24.04.1 LTS ||||
| A3 | Windows 11 ||||
| A4 | Debian GNU/Linux 11 (bullseye) || ❌ (Unreachable) | ❌ (Unreachable) |

#### **Final Output:**
- If `target_os="Linux"`: `["A1", "A2"]`
- If `target_os="Debian"`: `["A1"]`
- If `target_os=None`: `["A1", "A2", "A3"]` or `target_os` is undefined
2 changes: 1 addition & 1 deletion examples/aggregate_example.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: Echo some text in the terminal of the device
group: "Development"
target_os: "Debian"
target_os: "Linux" # <----
variables:
- name: package_manager
value: "apt"
Expand Down
38 changes: 28 additions & 10 deletions meshbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,22 +96,40 @@ async def compile_group_list(session: meshctrl.Session) -> dict:
return local_device_list

async def filter_targets(devices: list[dict], os_categories: dict, target_os: str = None) -> list[str]:
"""Filters devices based on reachability and optional OS criteria."""
"""Filters devices based on reachability and optional OS criteria, supporting nested OS categories."""
valid_devices = []

def get_os_variants(category: str, os_map: dict) -> set:
"""Extracts all OS names under a given category if it exists."""
for key, value in os_map.items():
if key == category:
if isinstance(value, dict): # Expand nested categories
os_set = set()
for subcat in value:
os_set.update(get_os_variants(subcat, value))
return os_set
elif isinstance(value, list): # Direct OS list
return set(value)
return set()

allowed_os = set()

# Identify correct OS filtering scope
for key in os_categories:
if key == target_os:
allowed_os = get_os_variants(target_os, os_categories)
break # Stop searching once a match is found

if isinstance(os_categories[key], dict) and target_os in os_categories[key]:
allowed_os = get_os_variants(target_os, os_categories[key])
break # Stop searching once a match is found

for device in devices:
if not device["reachable"]:
continue # Skip unreachable devices.

match target_os:
case None: # No filtering needed.
pass
case _ if target_os in os_categories and device["device_os"] in os_categories[target_os]:
pass # Allowed OS, continue processing.
case _:
continue # Skip if the OS is not in the allowed category.

valid_devices.append(device["device_id"])
if not target_os or device["device_os"] in allowed_os:
valid_devices.append(device["device_id"])

return valid_devices

Expand Down
21 changes: 14 additions & 7 deletions os_categories.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
{
"Debian": [
"Debian GNU/Linux 12 (bookworm)",
"Debian GNU/Linux 11 (bullseye)"
],
"Ubuntu": [
"Ubuntu 24.04.1 LTS"
]
"Linux": {
"Debian": [
"Debian GNU/Linux 12 (bookworm)",
"Debian GNU/Linux 11 (bullseye)"
],
"Ubuntu": [
"Ubuntu 24.04.1 LTS"
]
},
"MacOS": {
"Sequoia": [
"macOS 15.0.1"
]
}
}

0 comments on commit ab1105b

Please sign in to comment.