diff --git a/README.md b/README.md
index 42e6b52..5fbc162 100644
--- a/README.md
+++ b/README.md
@@ -20,37 +20,41 @@ To install, follow the following commands:
### Linux setup:
-```shell
+```bash
git clone https://github.com/daanselen/meshbook
cd ./meshbook
python3 -m venv ./venv
source ./venv/bin/activate
pip3 install -r ./requirements.txt
+cp ./templates/meshcentral.conf.template ./meshcentral.conf
```
-### Windows setup:
+### Windows setup (PowerShell, not cmd):
```shell
git clone https://github.com/daanselen/meshbook
cd ./meshbook
-python3 -m venv ./venv
+python -m venv ./venv # or python3 when done through the Microsoft Store.
.\venv\Scripts\activate # Make sure to check the terminal prefix.
pip3 install -r ./requirements.txt
+cp .\templates\meshcentral.conf.template .\meshcentral.conf
```
-Now copy the configuration template from ./templates and fill it in with the correct details. The url should start with `wss://`.
+Now copy the configuration template from ./templates and fill it in with the correct details (remove .template from the file) this is shown in the last step of the setup(s).
+The url should start with `wss://`.
+You can check pre-made examples in the examples directory, make sure the values are set to your situation.
After this you can use meshbook, for example:
### Linux run:
-```shell
+```bash
python3 .\meshbook.py -pb .\examples\echo.yaml
```
### Windows run:
```shell
-.\venv\Scripts\python.exe .\meshbook.py -pb .\examples\echo.yaml
+.\venv\Scripts\python.exe .\meshbook.py -pb .\examples\echo_example.yaml
```
### How to check if everything is okay?
@@ -80,6 +84,7 @@ So to target for example a mesh/group in MeshCentral called: "Nerthus" do:
---
name: example configuration
group: "Nerthus"
+#target_os: "Linux" # <--- according to os_categories.json
variables:
- name: var1
value: "This is the first variable"
@@ -118,6 +123,7 @@ You can expand the command chain as follows:
---
name: Echo a string to the terminal through the meshbook example.
group: "Dev"
+#target_os: "Linux" # <--- according to os_categories.json
variables:
- name: file
value: "/etc/os-release"
@@ -129,34 +135,30 @@ tasks:
The following response it received when executing the first yaml of the above files (without the `-s` parameters, which just outputs the below JSON).
```shell
-python3 meshbook.py -pb examples/echo_example.yaml
+~/meshbook$ python3 meshbook.py -pb examples/echo_example.yaml
+----------------------------------------
+Playbook: examples/echo_example.yaml
+Operating System Categorisation file: ./os_categories.json
+Congiguration file: ./meshcentral.conf
+Target group: Development
+Grace: True
+Silent: False
----------------------------------------
Trying to load the MeshCentral account credential file...
Trying to load the Playbook yaml file and compile it into something workable...
+Trying to load the Operating System categorisation JSON file...
Connecting to MeshCentral and establish a session using variables from previous credential file.
Generating group list with nodes and reference the targets from that.
----------------------------------------
-Executing playbook on the targets.
+Executing playbook on the target(s): Development.
+Initiating grace-period...
+1...
+2...
+3...
+----------------------------------------
1. Running: Echo!
----------------------------------------
-{
- "Task 1": [
- {
- "complete": true,
- "result": "PRETTY_NAME=\"Debian GNU/Linux 12 (bookworm)\" NAME=\"Debian GNU/Linux\" VERSION_ID=\"12\" VERSION=\"12 (bookworm)\" VERSION_CODENAME=bookworm ID=debian HOME_URL=\"https://www.debian.org/\" SUPPORT_URL=\"https://www.debian.org/support\" BUG_REPORT_URL=\"https://bugs.debian.org/\"\n",
- "command": "echo $(cat /etc/os-release)",
- "device_id": "",
- "device_name": "raspberrypi5"
- },
- {
- "complete": true,
- "result": "PRETTY_NAME=\"Debian GNU/Linux 12 (bookworm)\" NAME=\"Debian GNU/Linux\" VERSION_ID=\"12\" VERSION=\"12 (bookworm)\" VERSION_CODENAME=bookworm ID=debian HOME_URL=\"https://www.debian.org/\" SUPPORT_URL=\"https://www.debian.org/support\" BUG_REPORT_URL=\"https://bugs.debian.org/\"\n",
- "command": "echo $(cat /etc/os-release)",
- "device_id": "",
- "device_name": "Cubic"
- }
- ]
-}
+{"Task 1": "ALL THE DATA"} # Not sharing due to PID
```
The above without `-s` is quite verbose. use `--help` to read about parameters and getting a minimal response for example.
diff --git a/assets/meshbook_yaml_os.png b/assets/meshbook_yaml_os.png
deleted file mode 100644
index fb445cb..0000000
Binary files a/assets/meshbook_yaml_os.png and /dev/null differ
diff --git a/assets/meshcentral_os.png b/assets/meshcentral_os.png
deleted file mode 100644
index 5e419f2..0000000
Binary files a/assets/meshcentral_os.png and /dev/null differ
diff --git a/examples/apt_update_example.yaml b/examples/apt_update_example.yaml
index 332e081..f434ede 100644
--- a/examples/apt_update_example.yaml
+++ b/examples/apt_update_example.yaml
@@ -1,6 +1,7 @@
---
name: Refresh the apt cache
-device: Cubic
+device: ""
+#target_os: "Linux"
variables:
- name: package_manager
value: "apt"
diff --git a/examples/apt_upgrade_example.yaml b/examples/apt_upgrade_example.yaml
index 649b800..3b8b60f 100644
--- a/examples/apt_upgrade_example.yaml
+++ b/examples/apt_upgrade_example.yaml
@@ -1,6 +1,7 @@
---
name: Refresh the apt cache
group: "Dev"
+#target_os: "Linux"
variables:
- name: package_manager
value: "apt"
diff --git a/examples/echo_example.yaml b/examples/echo_example.yaml
index 6900e37..4c3f03f 100644
--- a/examples/echo_example.yaml
+++ b/examples/echo_example.yaml
@@ -1,7 +1,7 @@
---
name: Echo a string to the terminal through the meshbook example.
-group: "Dev"
-target_os: Debian GnU/Linux 12 (bookworm)
+group: "Development"
+target_os: "Linux"
variables:
- name: file
value: "/etc/os-release"
diff --git a/examples/variable_usage_example.yaml b/examples/variable_usage_example.yaml
index 0092773..c6deac6 100644
--- a/examples/variable_usage_example.yaml
+++ b/examples/variable_usage_example.yaml
@@ -1,6 +1,7 @@
---
name: Ping Multiple Points
group: "Kubernetes"
+#target_os: "Debian"
variables:
- name: host1
value: "1.1.1.1"
diff --git a/meshbook.py b/meshbook.py
index f84a9e7..d1c7f3e 100644
--- a/meshbook.py
+++ b/meshbook.py
@@ -141,21 +141,53 @@ async def gather_targets(playbook: dict, group_list: dict[str, list[dict]], os_c
target_list = []
target_os = playbook.get("target_os")
- if "device" in playbook:
- pseudo_target = playbook["device"]
+ async def process_device_or_group(pseudo_target, group_list, os_categories, target_os) -> list[str]:
+ """Helper function to process devices or groups."""
+ matched_devices = []
for group in group_list:
for device in group_list[group]:
if device["device_name"] == pseudo_target:
- matched_devices = await filter_targets([device], os_categories, target_os)
+ matched_devices.append(device)
+
+ if matched_devices:
+ return await filter_targets(matched_devices, os_categories, target_os)
+ return []
+
+ match playbook:
+ case {"device": pseudo_target}: # Single device target
+ if isinstance(pseudo_target, str):
+ matched_devices = await process_device_or_group(pseudo_target, group_list, os_categories, target_os)
+ target_list.extend(matched_devices)
+
+ else:
+ console("\033[91mPlease use devices (Notice the 'S') for multiple devices.\x1B[0m", True)
+
+ case {"devices": pseudo_target}: # List of devices
+ if isinstance(pseudo_target, list):
+ for sub_pseudo_device in pseudo_target:
+ matched_devices = await process_device_or_group(sub_pseudo_device, group_list, os_categories, target_os)
target_list.extend(matched_devices)
- elif "group" in playbook:
- pseudo_target = playbook["group"]
+ else:
+ console("\033[91mThe 'devices' method is being used, but only one string is given. Did you mean 'device'?\x1B[0m", True)
- if pseudo_target in group_list:
- matched_devices = await filter_targets(group_list[pseudo_target], os_categories, target_os)
- target_list.extend(matched_devices)
+ case {"group": pseudo_target}: # Single group target
+ if isinstance(pseudo_target, str) and pseudo_target in group_list:
+ matched_devices = await filter_targets(group_list[pseudo_target], os_categories, target_os)
+ target_list.extend(matched_devices)
+
+ else:
+ console("\033[91mPlease use groups (Notice the 'S') for multiple groups.\x1B[0m", True)
+
+ case {"groups": pseudo_target}: # List of groups
+ if isinstance(pseudo_target, list):
+ for sub_pseudo_target in pseudo_target:
+ if sub_pseudo_target in group_list:
+ matched_devices = await filter_targets(group_list[sub_pseudo_target], os_categories, target_os)
+ target_list.extend(matched_devices)
+ else:
+ console("\033[91mThe 'groups' method is being used, but only one string is given. Did you mean 'group'?\x1B[0m", True)
return target_list
@@ -220,10 +252,10 @@ async def main():
console("Operating System Categorisation file: " + args.oscategories)
console("Congiguration file: " + args.conf)
if "device" in playbook:
- console("Target device: " + playbook["device"])
+ console("Target device: " + str(playbook["device"]))
elif "group" in playbook:
- console("Target group: " + playbook["group"])
+ console("Target group: " + str(playbook["group"]))
console("Grace: " + str((not args.nograce))) # Negation of bool for correct explanation
console("Silent: False") # Can be pre-defined because if silent flag was passed then none of this would be printed.
@@ -249,7 +281,20 @@ async def main():
else:
console(("-" * 40))
- target_name = playbook["group"] if "group" in playbook else playbook["device"] # Quickly get the name.
+
+ match playbook:
+ case {"group": candidate_target_name}:
+ target_name = candidate_target_name
+
+ case {"groups": candidate_target_name}:
+ target_name = str(candidate_target_name)
+
+ case {"device": candidate_target_name}:
+ target_name = candidate_target_name
+
+ case {"devices": candidate_target_name}:
+ target_name = str(candidate_target_name)
+
console(("\033[91mExecuting playbook on the target(s): " + target_name + ".\x1B[0m"))
if not args.nograce: