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: