mirror of
https://github.com/DaanSelen/meshbook.git
synced 2026-02-20 08:22:11 +00:00
Added targeting of multiple groups and devices through a new 'keyword'
Through a new sorting method, all cool and logically formatted.
This commit is contained in:
54
README.md
54
README.md
@@ -20,37 +20,41 @@ To install, follow the following commands:<br>
|
|||||||
|
|
||||||
### Linux setup:
|
### Linux setup:
|
||||||
|
|
||||||
```shell
|
```bash
|
||||||
git clone https://github.com/daanselen/meshbook
|
git clone https://github.com/daanselen/meshbook
|
||||||
cd ./meshbook
|
cd ./meshbook
|
||||||
python3 -m venv ./venv
|
python3 -m venv ./venv
|
||||||
source ./venv/bin/activate
|
source ./venv/bin/activate
|
||||||
pip3 install -r ./requirements.txt
|
pip3 install -r ./requirements.txt
|
||||||
|
cp ./templates/meshcentral.conf.template ./meshcentral.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows setup:
|
### Windows setup (PowerShell, not cmd):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git clone https://github.com/daanselen/meshbook
|
git clone https://github.com/daanselen/meshbook
|
||||||
cd ./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.
|
.\venv\Scripts\activate # Make sure to check the terminal prefix.
|
||||||
pip3 install -r ./requirements.txt
|
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://`.<br>
|
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).<br>
|
||||||
|
The url should start with `wss://`.<br>
|
||||||
|
You can check pre-made examples in the examples directory, make sure the values are set to your situation.<br>
|
||||||
After this you can use meshbook, for example:
|
After this you can use meshbook, for example:
|
||||||
|
|
||||||
### Linux run:
|
### Linux run:
|
||||||
|
|
||||||
```shell
|
```bash
|
||||||
python3 .\meshbook.py -pb .\examples\echo.yaml
|
python3 .\meshbook.py -pb .\examples\echo.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows run:
|
### Windows run:
|
||||||
|
|
||||||
```shell
|
```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?
|
### 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
|
name: example configuration
|
||||||
group: "Nerthus"
|
group: "Nerthus"
|
||||||
|
#target_os: "Linux" # <--- according to os_categories.json
|
||||||
variables:
|
variables:
|
||||||
- name: var1
|
- name: var1
|
||||||
value: "This is the first variable"
|
value: "This is the first variable"
|
||||||
@@ -118,6 +123,7 @@ You can expand the command chain as follows:<br>
|
|||||||
---
|
---
|
||||||
name: Echo a string to the terminal through the meshbook example.
|
name: Echo a string to the terminal through the meshbook example.
|
||||||
group: "Dev"
|
group: "Dev"
|
||||||
|
#target_os: "Linux" # <--- according to os_categories.json
|
||||||
variables:
|
variables:
|
||||||
- name: file
|
- name: file
|
||||||
value: "/etc/os-release"
|
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).
|
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
|
```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 MeshCentral account credential file...
|
||||||
Trying to load the Playbook yaml file and compile it into something workable...
|
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.
|
Connecting to MeshCentral and establish a session using variables from previous credential file.
|
||||||
Generating group list with nodes and reference the targets from that.
|
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!
|
1. Running: Echo!
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
{
|
{"Task 1": "ALL THE DATA"} # Not sharing due to PID
|
||||||
"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": "<Node-Unique>",
|
|
||||||
"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": "<Node-Unique>",
|
|
||||||
"device_name": "Cubic"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
The above without `-s` is quite verbose. use `--help` to read about parameters and getting a minimal response for example.
|
The above without `-s` is quite verbose. use `--help` to read about parameters and getting a minimal response for example.
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB |
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: Refresh the apt cache
|
name: Refresh the apt cache
|
||||||
device: Cubic
|
device: "<Device-Name>"
|
||||||
|
#target_os: "Linux"
|
||||||
variables:
|
variables:
|
||||||
- name: package_manager
|
- name: package_manager
|
||||||
value: "apt"
|
value: "apt"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: Refresh the apt cache
|
name: Refresh the apt cache
|
||||||
group: "Dev"
|
group: "Dev"
|
||||||
|
#target_os: "Linux"
|
||||||
variables:
|
variables:
|
||||||
- name: package_manager
|
- name: package_manager
|
||||||
value: "apt"
|
value: "apt"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: Echo a string to the terminal through the meshbook example.
|
name: Echo a string to the terminal through the meshbook example.
|
||||||
group: "Dev"
|
group: "Development"
|
||||||
target_os: Debian GnU/Linux 12 (bookworm)
|
target_os: "Linux"
|
||||||
variables:
|
variables:
|
||||||
- name: file
|
- name: file
|
||||||
value: "/etc/os-release"
|
value: "/etc/os-release"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: Ping Multiple Points
|
name: Ping Multiple Points
|
||||||
group: "Kubernetes"
|
group: "Kubernetes"
|
||||||
|
#target_os: "Debian"
|
||||||
variables:
|
variables:
|
||||||
- name: host1
|
- name: host1
|
||||||
value: "1.1.1.1"
|
value: "1.1.1.1"
|
||||||
|
|||||||
67
meshbook.py
67
meshbook.py
@@ -141,21 +141,53 @@ async def gather_targets(playbook: dict, group_list: dict[str, list[dict]], os_c
|
|||||||
target_list = []
|
target_list = []
|
||||||
target_os = playbook.get("target_os")
|
target_os = playbook.get("target_os")
|
||||||
|
|
||||||
if "device" in playbook:
|
async def process_device_or_group(pseudo_target, group_list, os_categories, target_os) -> list[str]:
|
||||||
pseudo_target = playbook["device"]
|
"""Helper function to process devices or groups."""
|
||||||
|
|
||||||
|
matched_devices = []
|
||||||
for group in group_list:
|
for group in group_list:
|
||||||
for device in group_list[group]:
|
for device in group_list[group]:
|
||||||
if device["device_name"] == pseudo_target:
|
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)
|
target_list.extend(matched_devices)
|
||||||
|
|
||||||
elif "group" in playbook:
|
else:
|
||||||
pseudo_target = playbook["group"]
|
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:
|
case {"group": pseudo_target}: # Single group target
|
||||||
matched_devices = await filter_targets(group_list[pseudo_target], os_categories, target_os)
|
if isinstance(pseudo_target, str) and pseudo_target in group_list:
|
||||||
target_list.extend(matched_devices)
|
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
|
return target_list
|
||||||
|
|
||||||
@@ -220,10 +252,10 @@ async def main():
|
|||||||
console("Operating System Categorisation file: " + args.oscategories)
|
console("Operating System Categorisation file: " + args.oscategories)
|
||||||
console("Congiguration file: " + args.conf)
|
console("Congiguration file: " + args.conf)
|
||||||
if "device" in playbook:
|
if "device" in playbook:
|
||||||
console("Target device: " + playbook["device"])
|
console("Target device: " + str(playbook["device"]))
|
||||||
|
|
||||||
elif "group" in playbook:
|
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("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.
|
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:
|
else:
|
||||||
console(("-" * 40))
|
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"))
|
console(("\033[91mExecuting playbook on the target(s): " + target_name + ".\x1B[0m"))
|
||||||
|
|
||||||
if not args.nograce:
|
if not args.nograce:
|
||||||
|
|||||||
Reference in New Issue
Block a user