machineconfig 5.15__py3-none-any.whl → 7.98__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- machineconfig/__init__.py +0 -28
- machineconfig/cluster/remote/cloud_manager.py +1 -1
- machineconfig/cluster/remote/distribute.py +0 -1
- machineconfig/cluster/remote/file_manager.py +0 -2
- machineconfig/cluster/remote/script_execution.py +0 -1
- machineconfig/cluster/sessions_managers/{utils → helpers}/enhanced_command_runner.py +4 -6
- machineconfig/cluster/sessions_managers/utils/load_balancer.py +1 -1
- machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
- machineconfig/cluster/sessions_managers/wt_local.py +114 -289
- machineconfig/cluster/sessions_managers/wt_local_manager.py +70 -210
- machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +52 -198
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
- machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
- machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
- machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
- machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +25 -170
- machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +16 -12
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
- machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
- machineconfig/jobs/{python → installer}/check_installations.py +2 -3
- machineconfig/jobs/installer/custom/boxes.py +61 -0
- machineconfig/jobs/installer/custom/hx.py +76 -19
- machineconfig/jobs/installer/custom/yazi.py +119 -0
- machineconfig/jobs/installer/custom_dev/alacritty.py +4 -4
- machineconfig/jobs/installer/custom_dev/brave.py +5 -9
- machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/custom_dev/code.py +4 -1
- machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
- machineconfig/jobs/installer/custom_dev/nerdfont.py +1 -1
- machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +33 -28
- machineconfig/jobs/installer/custom_dev/sysabc.py +139 -0
- machineconfig/jobs/installer/custom_dev/wezterm.py +2 -19
- machineconfig/jobs/installer/custom_dev/winget.py +10 -14
- machineconfig/jobs/installer/installer_data.json +1487 -229
- machineconfig/jobs/installer/linux_scripts/brave.sh +4 -14
- machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +5 -17
- machineconfig/jobs/installer/linux_scripts/docker.sh +5 -17
- machineconfig/jobs/installer/linux_scripts/docker_start.sh +6 -14
- machineconfig/jobs/installer/linux_scripts/edge.sh +3 -11
- machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
- machineconfig/jobs/installer/linux_scripts/nerdfont.sh +5 -17
- machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
- machineconfig/jobs/installer/linux_scripts/q.sh +10 -6
- machineconfig/jobs/installer/linux_scripts/redis.sh +6 -17
- machineconfig/jobs/installer/linux_scripts/vscode.sh +5 -17
- machineconfig/jobs/installer/linux_scripts/wezterm.sh +4 -12
- machineconfig/jobs/installer/package_groups.py +106 -177
- machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
- machineconfig/logger.py +0 -1
- machineconfig/profile/backup.toml +49 -0
- machineconfig/profile/bash_shell_profiles.md +11 -0
- machineconfig/profile/create_helper.py +62 -0
- machineconfig/profile/create_links.py +288 -0
- machineconfig/profile/create_links_export.py +100 -0
- machineconfig/profile/create_shell_profile.py +147 -0
- machineconfig/profile/mapper.toml +263 -0
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
- machineconfig/scripts/linux/wrap_mcfg +46 -0
- machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
- machineconfig/scripts/python/agents.py +123 -117
- machineconfig/scripts/python/ai/initai.py +3 -28
- machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
- machineconfig/scripts/python/ai/scripts/command_runner.sh +9 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +17 -18
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +17 -18
- machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
- machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +5 -5
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +5 -1
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
- machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
- machineconfig/scripts/python/ai/solutions/generic.py +28 -5
- machineconfig/scripts/python/ai/utils/generate_files.py +348 -0
- machineconfig/scripts/python/ai/utils/vscode_tasks.py +37 -0
- machineconfig/scripts/python/cloud.py +29 -0
- machineconfig/scripts/python/croshell.py +137 -113
- machineconfig/scripts/python/devops.py +61 -101
- machineconfig/scripts/python/devops_navigator.py +6 -0
- machineconfig/scripts/python/env_manager/__init__.py +1 -0
- machineconfig/scripts/python/env_manager/env_manager_tui.py +204 -0
- machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
- machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
- machineconfig/scripts/python/fire_jobs.py +110 -150
- machineconfig/scripts/python/ftpx.py +51 -24
- machineconfig/scripts/python/helpers/ast_search.py +74 -0
- machineconfig/scripts/python/helpers/qr_code.py +166 -0
- machineconfig/scripts/python/helpers/repo_rag.py +325 -0
- machineconfig/scripts/python/helpers/run_py_script.py +79 -0
- machineconfig/scripts/python/helpers/symantic_search.py +25 -0
- machineconfig/scripts/python/helpers/tmp_py_scripts/a.py +26 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +126 -0
- machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +41 -0
- machineconfig/scripts/python/helpers_agents/templates/prompt.txt +10 -0
- machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
- machineconfig/scripts/python/helpers_agents/templates/template.sh +32 -0
- machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +30 -23
- machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +29 -35
- machineconfig/scripts/python/{cloud_sync.py → helpers_cloud/cloud_sync.py} +12 -18
- machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +1 -1
- machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
- machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +8 -9
- machineconfig/scripts/python/helpers_devops/cli_config.py +105 -0
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
- machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
- machineconfig/scripts/python/helpers_devops/cli_nw.py +214 -0
- machineconfig/scripts/python/helpers_devops/cli_repos.py +215 -0
- machineconfig/scripts/python/helpers_devops/cli_self.py +172 -0
- machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +142 -0
- machineconfig/scripts/python/{share_terminal.py → helpers_devops/cli_share_terminal.py} +45 -35
- machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
- machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
- machineconfig/scripts/python/helpers_devops/devops_status.py +499 -0
- machineconfig/scripts/python/{devops_update_repos.py → helpers_devops/devops_update_repos.py} +68 -49
- machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
- machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
- machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +3 -3
- machineconfig/scripts/python/helpers_fire_command/__init__.py +0 -0
- machineconfig/scripts/python/helpers_fire_command/f.py +0 -0
- machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +56 -20
- machineconfig/scripts/python/{fire_jobs_args_helper.py → helpers_fire_command/fire_jobs_args_helper.py} +5 -1
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +121 -0
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_streamlit_helper.py +0 -0
- machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
- machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +3 -3
- machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
- machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
- machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
- machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
- machineconfig/scripts/python/helpers_navigator/command_tree.py +620 -0
- machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
- machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
- machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
- machineconfig/scripts/python/helpers_network/__init__.py +0 -0
- machineconfig/scripts/python/helpers_network/address.py +132 -0
- machineconfig/scripts/python/{devops_add_identity.py → helpers_network/devops_add_identity.py} +0 -2
- machineconfig/scripts/python/helpers_network/devops_add_ssh_key.py +153 -0
- machineconfig/scripts/{linux → python/helpers_network}/mount_nfs +0 -1
- machineconfig/scripts/python/{mount_nfs.py → helpers_network/mount_nfs.py} +3 -3
- machineconfig/scripts/{linux → python/helpers_network}/mount_nw_drive +1 -2
- machineconfig/scripts/python/{mount_ssh.py → helpers_network/mount_ssh.py} +3 -3
- machineconfig/scripts/python/{onetimeshare.py → helpers_network/onetimeshare.py} +0 -1
- machineconfig/scripts/python/helpers_network/ssh_debug_linux.py +391 -0
- machineconfig/scripts/python/helpers_network/ssh_debug_windows.py +338 -0
- machineconfig/scripts/python/{wifi_conn.py → helpers_network/wifi_conn.py} +1 -53
- machineconfig/scripts/python/{wsl_windows_transfer.py → helpers_network/wsl_windows_transfer.py} +5 -4
- machineconfig/scripts/python/helpers_repos/action.py +209 -0
- machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
- machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +2 -3
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
- machineconfig/scripts/python/{repos_helper.py → helpers_repos/entrypoint.py} +9 -17
- machineconfig/scripts/python/helpers_repos/grource.py +340 -0
- machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +4 -3
- machineconfig/scripts/python/helpers_repos/repo_analyzer_1.py +160 -0
- machineconfig/scripts/python/{count_lines.py → helpers_repos/repo_analyzer_2.py} +113 -192
- machineconfig/scripts/python/helpers_repos/sync.py +66 -0
- machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
- machineconfig/scripts/python/helpers_sessions/__init__.py +0 -0
- machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +65 -0
- machineconfig/scripts/python/helpers_utils/download.py +150 -0
- machineconfig/scripts/python/helpers_utils/path.py +185 -0
- machineconfig/scripts/python/interactive.py +64 -84
- machineconfig/scripts/python/mcfg_entry.py +58 -0
- machineconfig/scripts/python/msearch.py +71 -0
- machineconfig/scripts/python/sessions.py +119 -45
- machineconfig/scripts/python/terminal.py +133 -0
- machineconfig/scripts/python/utils.py +64 -0
- machineconfig/scripts/windows/mounts/Restore-ThunderbirdProfile.ps1 +92 -0
- machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
- machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
- machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
- machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
- machineconfig/settings/broot/br.sh +0 -4
- machineconfig/settings/broot/conf.toml +1 -1
- machineconfig/settings/helix/config.toml +16 -0
- machineconfig/settings/helix/languages.toml +13 -4
- machineconfig/settings/helix/yazi-picker.sh +12 -0
- machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
- machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
- machineconfig/settings/lf/linux/lfrc +10 -12
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/lf/windows/lfrc +18 -38
- machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
- machineconfig/settings/linters/.ruff.toml +1 -1
- machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
- machineconfig/settings/marimo/marimo.toml +80 -0
- machineconfig/settings/marimo/snippets/globalize.py +34 -0
- machineconfig/settings/pistol/pistol.conf +1 -1
- machineconfig/settings/shells/bash/init.sh +82 -31
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
- machineconfig/settings/shells/nushell/config.nu +2 -35
- machineconfig/settings/shells/nushell/env.nu +45 -6
- machineconfig/settings/shells/nushell/init.nu +314 -0
- machineconfig/settings/shells/pwsh/init.ps1 +61 -43
- machineconfig/settings/shells/starship/starship.toml +16 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
- machineconfig/settings/shells/wt/settings.json +32 -17
- machineconfig/settings/shells/zsh/init.sh +89 -0
- machineconfig/settings/svim/linux/init.toml +0 -4
- machineconfig/settings/svim/windows/init.toml +0 -3
- machineconfig/settings/television/cable_unix/alias.toml +8 -0
- machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
- machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
- machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
- machineconfig/settings/television/cable_unix/channels.toml +19 -0
- machineconfig/settings/television/cable_unix/dirs.toml +13 -0
- machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
- machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
- machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_unix/env.toml +17 -0
- machineconfig/settings/television/cable_unix/files.toml +11 -0
- machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
- machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
- machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
- machineconfig/settings/television/cable_unix/git-log.toml +12 -0
- machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
- machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
- machineconfig/settings/television/cable_unix/guix.toml +20 -0
- machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
- machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
- machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
- machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
- machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
- machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
- machineconfig/settings/television/cable_unix/procs.toml +20 -0
- machineconfig/settings/television/cable_unix/text.toml +17 -0
- machineconfig/settings/television/cable_unix/tldr.toml +18 -0
- machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
- machineconfig/settings/television/cable_windows/alias.toml +7 -0
- machineconfig/settings/television/cable_windows/dirs.toml +13 -0
- machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
- machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_windows/env.toml +17 -0
- machineconfig/settings/television/cable_windows/files.toml +14 -0
- machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
- machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
- machineconfig/settings/television/cable_windows/git-log.toml +11 -0
- machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
- machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
- machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
- machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
- machineconfig/settings/television/cable_windows/text.toml +17 -0
- machineconfig/settings/yazi/init.lua +61 -0
- machineconfig/settings/yazi/keymap_linux.toml +94 -0
- machineconfig/settings/yazi/keymap_windows.toml +78 -0
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
- machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
- machineconfig/settings/yazi/theme.toml +4 -0
- machineconfig/settings/yazi/yazi_linux.toml +84 -0
- machineconfig/settings/yazi/yazi_windows.toml +58 -0
- machineconfig/setup_linux/__init__.py +11 -0
- machineconfig/setup_linux/apps_desktop.sh +89 -0
- machineconfig/setup_linux/apps_gui.sh +64 -0
- machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
- machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
- machineconfig/setup_linux/uv.sh +15 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +26 -6
- machineconfig/setup_linux/web_shortcuts/live_from_github.sh +31 -0
- machineconfig/setup_mac/__init__.py +16 -0
- machineconfig/setup_mac/apps_gui.sh +248 -0
- machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
- machineconfig/setup_mac/uv.sh +36 -0
- machineconfig/setup_windows/__init__.py +11 -0
- machineconfig/setup_windows/others/power_options.ps1 +7 -0
- machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
- machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
- machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
- machineconfig/setup_windows/uv.ps1 +17 -0
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +27 -10
- machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +30 -0
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
- machineconfig/utils/accessories.py +7 -5
- machineconfig/utils/cloud/onedrive/README.md +139 -0
- machineconfig/utils/code.py +155 -105
- machineconfig/utils/files/art/fat_croco.txt +10 -0
- machineconfig/utils/files/art/halfwit_croco.txt +9 -0
- machineconfig/utils/files/art/happy_croco.txt +22 -0
- machineconfig/utils/files/art/water_croco.txt +11 -0
- machineconfig/utils/files/ascii_art.py +1 -1
- machineconfig/utils/files/dbms.py +257 -0
- machineconfig/utils/files/headers.py +11 -14
- machineconfig/utils/files/ouch/__init__.py +0 -0
- machineconfig/utils/files/ouch/decompress.py +45 -0
- machineconfig/utils/files/read.py +10 -18
- machineconfig/utils/installer_utils/github_release_bulk.py +156 -119
- machineconfig/utils/installer_utils/install_from_url.py +183 -0
- machineconfig/utils/installer_utils/installer_class.py +64 -181
- machineconfig/utils/installer_utils/installer_cli.py +175 -0
- machineconfig/utils/installer_utils/installer_helper.py +129 -0
- machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +66 -97
- machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +49 -82
- machineconfig/utils/io.py +77 -23
- machineconfig/utils/links.py +254 -162
- machineconfig/utils/meta.py +256 -0
- machineconfig/utils/notifications.py +1 -1
- machineconfig/utils/options.py +46 -18
- machineconfig/utils/options_tv.py +119 -0
- machineconfig/utils/path_extended.py +48 -101
- machineconfig/utils/path_helper.py +76 -23
- machineconfig/utils/procs.py +50 -70
- machineconfig/utils/scheduler.py +88 -124
- machineconfig/utils/scheduling.py +0 -3
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
- machineconfig/utils/schemas/layouts/layout_types.py +1 -1
- machineconfig/utils/source_of_truth.py +3 -6
- machineconfig/utils/ssh.py +263 -274
- machineconfig/utils/ssh_utils/abc.py +5 -0
- machineconfig/utils/ssh_utils/copy_from_here.py +111 -0
- machineconfig/utils/ssh_utils/copy_to_here.py +302 -0
- machineconfig/utils/ssh_utils/utils.py +142 -0
- machineconfig/utils/ssh_utils/wsl.py +210 -0
- machineconfig/utils/terminal.py +3 -113
- machineconfig/utils/tst.py +20 -0
- machineconfig/utils/upgrade_packages.py +114 -28
- machineconfig/utils/ve.py +12 -4
- machineconfig-7.98.dist-info/METADATA +132 -0
- machineconfig-7.98.dist-info/RECORD +504 -0
- machineconfig-7.98.dist-info/entry_points.txt +13 -0
- machineconfig/cluster/sessions_managers/ffile.py +0 -4
- machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -49
- machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -85
- machineconfig/jobs/linux/msc/cli_agents.sh +0 -16
- machineconfig/jobs/python/python_ve_symlink.py +0 -37
- machineconfig/jobs/python/vscode/api.py +0 -57
- machineconfig/jobs/python/vscode/sync_code.py +0 -73
- machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
- machineconfig/jobs/windows/start_terminal.ps1 +0 -6
- machineconfig/jobs/windows/startup_file.cmd +0 -2
- machineconfig/profile/create.py +0 -303
- machineconfig/profile/shell.py +0 -176
- machineconfig/scripts/cloud/init.sh +0 -119
- machineconfig/scripts/linux/agents +0 -2
- machineconfig/scripts/linux/choose_wezterm_theme +0 -3
- machineconfig/scripts/linux/cloud_copy +0 -2
- machineconfig/scripts/linux/cloud_mount +0 -2
- machineconfig/scripts/linux/cloud_repo_sync +0 -2
- machineconfig/scripts/linux/cloud_sync +0 -2
- machineconfig/scripts/linux/croshell +0 -3
- machineconfig/scripts/linux/devops +0 -2
- machineconfig/scripts/linux/fire +0 -2
- machineconfig/scripts/linux/ftpx +0 -2
- machineconfig/scripts/linux/fzf2g +0 -21
- machineconfig/scripts/linux/fzfag +0 -17
- machineconfig/scripts/linux/fzffg +0 -25
- machineconfig/scripts/linux/fzfrga +0 -21
- machineconfig/scripts/linux/gh_models +0 -2
- machineconfig/scripts/linux/initai +0 -2
- machineconfig/scripts/linux/kill_process +0 -2
- machineconfig/scripts/linux/scheduler +0 -2
- machineconfig/scripts/linux/sessions +0 -2
- machineconfig/scripts/linux/share_smb +0 -1
- machineconfig/scripts/linux/skrg +0 -4
- machineconfig/scripts/linux/start_slidev +0 -2
- machineconfig/scripts/linux/start_terminals +0 -3
- machineconfig/scripts/linux/warp-cli.sh +0 -122
- machineconfig/scripts/linux/wifi_conn +0 -2
- machineconfig/scripts/linux/z_ls +0 -104
- machineconfig/scripts/python/ai/generate_files.py +0 -83
- machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
- machineconfig/scripts/python/cloud_repo_sync.py +0 -190
- machineconfig/scripts/python/count_lines_frontend.py +0 -16
- machineconfig/scripts/python/devops_add_ssh_key.py +0 -120
- machineconfig/scripts/python/dotfile.py +0 -78
- machineconfig/scripts/python/fire_agents_help_launch.py +0 -120
- machineconfig/scripts/python/fire_agents_helper_types.py +0 -12
- machineconfig/scripts/python/fire_jobs_route_helper.py +0 -65
- machineconfig/scripts/python/get_zellij_cmd.py +0 -15
- machineconfig/scripts/python/gh_models.py +0 -104
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -116
- machineconfig/scripts/python/repos.py +0 -132
- machineconfig/scripts/python/repos_helper_action.py +0 -378
- machineconfig/scripts/python/snapshot.py +0 -25
- machineconfig/scripts/python/start_terminals.py +0 -121
- machineconfig/scripts/python/t4.py +0 -17
- machineconfig/scripts/windows/agents.ps1 +0 -1
- machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
- machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
- machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
- machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
- machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
- machineconfig/scripts/windows/croshell.ps1 +0 -1
- machineconfig/scripts/windows/devops.ps1 +0 -1
- machineconfig/scripts/windows/dotfile.ps1 +0 -1
- machineconfig/scripts/windows/fire.ps1 +0 -1
- machineconfig/scripts/windows/ftpx.ps1 +0 -1
- machineconfig/scripts/windows/fzfb.ps1 +0 -3
- machineconfig/scripts/windows/fzfg.ps1 +0 -2
- machineconfig/scripts/windows/fzfrga.bat +0 -20
- machineconfig/scripts/windows/gpt.ps1 +0 -1
- machineconfig/scripts/windows/grep.ps1 +0 -2
- machineconfig/scripts/windows/initai.ps1 +0 -1
- machineconfig/scripts/windows/kill_process.ps1 +0 -1
- machineconfig/scripts/windows/nano.ps1 +0 -3
- machineconfig/scripts/windows/pomodoro.ps1 +0 -1
- machineconfig/scripts/windows/reload_path.ps1 +0 -3
- machineconfig/scripts/windows/scheduler.ps1 +0 -1
- machineconfig/scripts/windows/sessions.ps1 +0 -1
- machineconfig/scripts/windows/snapshot.ps1 +0 -1
- machineconfig/scripts/windows/start_slidev.ps1 +0 -1
- machineconfig/scripts/windows/start_terminals.ps1 +0 -1
- machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
- machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
- machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
- machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
- machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
- machineconfig/settings/lf/windows/tst.ps1 +0 -1
- machineconfig/settings/yazi/yazi.toml +0 -4
- machineconfig/setup_linux/nix/cli_installation.sh +0 -157
- machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
- machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
- machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
- machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
- machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
- machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
- machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
- machineconfig/utils/ai/generate_file_checklist.py +0 -68
- machineconfig/utils/installer_utils/installer.py +0 -189
- machineconfig-5.15.dist-info/METADATA +0 -188
- machineconfig-5.15.dist-info/RECORD +0 -415
- machineconfig-5.15.dist-info/entry_points.txt +0 -18
- machineconfig/cluster/sessions_managers/{utils → helpers}/load_balancer_helper.py +0 -0
- machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
- machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
- machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
- machineconfig/{jobs/python → scripts/python/ai/utils}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers → helpers_agents}/__init__.py +0 -0
- machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_agents/agentic_frameworks/__init__.py} +0 -0
- machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
- machineconfig/scripts/python/{fire_agents_load_balancer.py → helpers_agents/fire_agents_load_balancer.py} +0 -0
- machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_cloud/__init__.py} +0 -0
- machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
- /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
- /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_croshell/__init__.py} +0 -0
- /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
- /machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -0
- /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
- /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
- /machineconfig/scripts/{windows/share_nfs.ps1 → python/helpers_devops/__init__.py} +0 -0
- /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers_devops/themes/__init__.py} +0 -0
- /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
- /machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -0
- /machineconfig/scripts/{linux → python/helpers_network}/mount_drive +0 -0
- /machineconfig/scripts/python/{mount_nw_drive.py → helpers_network/mount_nw_drive.py} +0 -0
- /machineconfig/scripts/{linux → python/helpers_network}/mount_smb +0 -0
- /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
- /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
- /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
- /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
- /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
- /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
- /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
- {machineconfig-5.15.dist-info → machineconfig-7.98.dist-info}/WHEEL +0 -0
- {machineconfig-5.15.dist-info → machineconfig-7.98.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Main TUI application for navigating machineconfig commands.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import subprocess
|
|
6
|
+
from textual.app import App, ComposeResult
|
|
7
|
+
from textual.widgets import Header, Footer, Input, Tree
|
|
8
|
+
from textual.binding import Binding
|
|
9
|
+
from machineconfig.scripts.python.helpers_navigator.command_builder import CommandBuilderScreen
|
|
10
|
+
from machineconfig.scripts.python.helpers_navigator.command_tree import CommandTree
|
|
11
|
+
from machineconfig.scripts.python.helpers_navigator.command_detail import CommandDetail
|
|
12
|
+
from machineconfig.scripts.python.helpers_navigator.search_bar import SearchBar
|
|
13
|
+
from machineconfig.scripts.python.helpers_navigator.data_models import CommandInfo
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CommandNavigatorApp(App[None]):
|
|
17
|
+
"""TUI application for navigating machineconfig commands."""
|
|
18
|
+
|
|
19
|
+
CSS = """
|
|
20
|
+
Screen {
|
|
21
|
+
layout: grid;
|
|
22
|
+
grid-size: 2 3;
|
|
23
|
+
grid-rows: auto 1fr auto;
|
|
24
|
+
grid-columns: 1fr 1fr;
|
|
25
|
+
height: 100%;
|
|
26
|
+
width: 100%;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Header {
|
|
30
|
+
column-span: 2;
|
|
31
|
+
background: $boost;
|
|
32
|
+
color: $text;
|
|
33
|
+
width: 100%;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#search-bar {
|
|
37
|
+
column-span: 2;
|
|
38
|
+
padding: 1;
|
|
39
|
+
background: $surface;
|
|
40
|
+
height: auto;
|
|
41
|
+
width: 100%;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.search-label {
|
|
45
|
+
width: auto;
|
|
46
|
+
padding-right: 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#search-input {
|
|
50
|
+
width: 1fr;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#command-tree {
|
|
54
|
+
row-span: 1;
|
|
55
|
+
border: solid $primary;
|
|
56
|
+
padding: 1;
|
|
57
|
+
width: 100%;
|
|
58
|
+
height: 100%;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#command-detail {
|
|
62
|
+
row-span: 1;
|
|
63
|
+
border: solid $primary;
|
|
64
|
+
padding: 1;
|
|
65
|
+
width: 100%;
|
|
66
|
+
height: 100%;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Footer {
|
|
70
|
+
column-span: 2;
|
|
71
|
+
background: $boost;
|
|
72
|
+
width: 100%;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Button {
|
|
76
|
+
margin: 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
CommandBuilderScreen {
|
|
80
|
+
align: center middle;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
CommandBuilderScreen > VerticalScroll {
|
|
84
|
+
width: 80;
|
|
85
|
+
height: auto;
|
|
86
|
+
max-height: 90%;
|
|
87
|
+
background: $surface;
|
|
88
|
+
border: thick $primary;
|
|
89
|
+
padding: 2;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
CommandBuilderScreen .title {
|
|
93
|
+
margin-bottom: 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
CommandBuilderScreen Label {
|
|
97
|
+
margin-top: 1;
|
|
98
|
+
margin-bottom: 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
CommandBuilderScreen Input {
|
|
102
|
+
margin-bottom: 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
CommandBuilderScreen .buttons {
|
|
106
|
+
margin-top: 2;
|
|
107
|
+
height: auto;
|
|
108
|
+
align: center middle;
|
|
109
|
+
}
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
BINDINGS = [
|
|
113
|
+
Binding("q", "quit", "Quit", priority=True),
|
|
114
|
+
Binding("c", "copy_command", "Copy Command"),
|
|
115
|
+
Binding("/", "focus_search", "Search"),
|
|
116
|
+
Binding("?", "help", "Help"),
|
|
117
|
+
Binding("r", "run_command", "Run Command"),
|
|
118
|
+
Binding("b", "build_command", "Build Command"),
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
def compose(self) -> ComposeResult:
|
|
122
|
+
"""Create child widgets for the app."""
|
|
123
|
+
yield Header(show_clock=True)
|
|
124
|
+
yield SearchBar(id="search-bar")
|
|
125
|
+
yield CommandTree("📚 machineconfig Commands", id="command-tree")
|
|
126
|
+
yield CommandDetail(id="command-detail")
|
|
127
|
+
yield Footer()
|
|
128
|
+
|
|
129
|
+
def on_mount(self) -> None:
|
|
130
|
+
"""Actions when app is mounted."""
|
|
131
|
+
self.title = "machineconfig Command Navigator"
|
|
132
|
+
self.sub_title = "Navigate and explore all available commands"
|
|
133
|
+
tree = self.query_one(CommandTree)
|
|
134
|
+
tree.focus()
|
|
135
|
+
|
|
136
|
+
def on_tree_node_selected(self, event: Tree.NodeSelected[CommandInfo]) -> None:
|
|
137
|
+
"""Handle tree node selection."""
|
|
138
|
+
command_info = event.node.data
|
|
139
|
+
detail_widget = self.query_one("#command-detail", CommandDetail)
|
|
140
|
+
detail_widget.update_command(command_info)
|
|
141
|
+
|
|
142
|
+
def on_input_changed(self, event: Input.Changed) -> None:
|
|
143
|
+
"""Handle search input changes."""
|
|
144
|
+
if event.input.id != "search-input":
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
search_term = event.value.lower()
|
|
148
|
+
tree = self.query_one(CommandTree)
|
|
149
|
+
|
|
150
|
+
if not search_term:
|
|
151
|
+
# Show all nodes - expand all root children
|
|
152
|
+
for node in tree.root.children:
|
|
153
|
+
node.expand()
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
# Filter nodes based on search term
|
|
157
|
+
def filter_tree(node): # type: ignore
|
|
158
|
+
if node.data and not node.data.is_group:
|
|
159
|
+
match = (search_term in node.data.name.lower() or
|
|
160
|
+
search_term in node.data.description.lower() or
|
|
161
|
+
search_term in node.data.command.lower())
|
|
162
|
+
return match
|
|
163
|
+
return False
|
|
164
|
+
|
|
165
|
+
# Expand parents of matching nodes by walking through all nodes
|
|
166
|
+
def walk_nodes(node): # type: ignore
|
|
167
|
+
"""Recursively walk through tree nodes."""
|
|
168
|
+
yield node
|
|
169
|
+
for child in node.children:
|
|
170
|
+
yield from walk_nodes(child)
|
|
171
|
+
|
|
172
|
+
for node in walk_nodes(tree.root):
|
|
173
|
+
if filter_tree(node):
|
|
174
|
+
parent = node.parent
|
|
175
|
+
while parent and parent != tree.root:
|
|
176
|
+
parent.expand()
|
|
177
|
+
parent = parent.parent # type: ignore
|
|
178
|
+
|
|
179
|
+
def action_copy_command(self) -> None:
|
|
180
|
+
"""Copy the selected command to clipboard."""
|
|
181
|
+
tree = self.query_one(CommandTree)
|
|
182
|
+
if tree.cursor_node and tree.cursor_node.data:
|
|
183
|
+
command = tree.cursor_node.data.command
|
|
184
|
+
try:
|
|
185
|
+
import pyperclip # type: ignore
|
|
186
|
+
pyperclip.copy(command)
|
|
187
|
+
self.notify(f"Copied: {command}", severity="information")
|
|
188
|
+
except ImportError:
|
|
189
|
+
self.notify("Install pyperclip to enable clipboard support", severity="warning")
|
|
190
|
+
|
|
191
|
+
def action_run_command(self) -> None:
|
|
192
|
+
"""Run the selected command without arguments."""
|
|
193
|
+
tree = self.query_one(CommandTree)
|
|
194
|
+
if tree.cursor_node and tree.cursor_node.data:
|
|
195
|
+
command_info = tree.cursor_node.data
|
|
196
|
+
if command_info.is_group:
|
|
197
|
+
self.notify("Cannot run command groups directly", severity="warning")
|
|
198
|
+
return
|
|
199
|
+
|
|
200
|
+
self._execute_command(command_info.command)
|
|
201
|
+
|
|
202
|
+
def action_build_command(self) -> None:
|
|
203
|
+
"""Open command builder for selected command."""
|
|
204
|
+
tree = self.query_one(CommandTree)
|
|
205
|
+
if tree.cursor_node and tree.cursor_node.data:
|
|
206
|
+
command_info = tree.cursor_node.data
|
|
207
|
+
if command_info.is_group:
|
|
208
|
+
self.notify("Cannot build command for groups", severity="warning")
|
|
209
|
+
return
|
|
210
|
+
|
|
211
|
+
self.push_screen(CommandBuilderScreen(command_info), self._handle_builder_result)
|
|
212
|
+
|
|
213
|
+
def _handle_builder_result(self, result: str | None) -> None:
|
|
214
|
+
"""Handle result from command builder."""
|
|
215
|
+
if not result:
|
|
216
|
+
return
|
|
217
|
+
|
|
218
|
+
if result.startswith("EXECUTE:"):
|
|
219
|
+
command = result[8:]
|
|
220
|
+
self._execute_command(command)
|
|
221
|
+
elif result.startswith("COPY:"):
|
|
222
|
+
command = result[5:]
|
|
223
|
+
self._copy_to_clipboard(command)
|
|
224
|
+
|
|
225
|
+
def _execute_command(self, command: str) -> None:
|
|
226
|
+
"""Execute a shell command."""
|
|
227
|
+
try:
|
|
228
|
+
self.notify(f"Executing: {command}", severity="information")
|
|
229
|
+
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=30)
|
|
230
|
+
|
|
231
|
+
if result.returncode == 0:
|
|
232
|
+
output = result.stdout.strip()
|
|
233
|
+
if output:
|
|
234
|
+
self.notify(f"Success: {output[:100]}...", severity="information", timeout=5)
|
|
235
|
+
else:
|
|
236
|
+
self.notify("Command executed successfully", severity="information")
|
|
237
|
+
else:
|
|
238
|
+
error = result.stderr.strip() or "Unknown error"
|
|
239
|
+
self.notify(f"Error: {error[:100]}...", severity="error", timeout=10)
|
|
240
|
+
except subprocess.TimeoutExpired:
|
|
241
|
+
self.notify("Command timed out after 30 seconds", severity="warning")
|
|
242
|
+
except Exception as e:
|
|
243
|
+
self.notify(f"Failed to execute: {str(e)}", severity="error")
|
|
244
|
+
|
|
245
|
+
def _copy_to_clipboard(self, command: str) -> None:
|
|
246
|
+
"""Copy command to clipboard."""
|
|
247
|
+
try:
|
|
248
|
+
import pyperclip # type: ignore
|
|
249
|
+
pyperclip.copy(command)
|
|
250
|
+
self.notify(f"Copied: {command}", severity="information")
|
|
251
|
+
except ImportError:
|
|
252
|
+
self.notify("Install pyperclip to enable clipboard support", severity="warning")
|
|
253
|
+
|
|
254
|
+
def action_focus_search(self) -> None:
|
|
255
|
+
"""Focus the search input."""
|
|
256
|
+
search_input = self.query_one("#search-input", Input)
|
|
257
|
+
search_input.focus()
|
|
258
|
+
|
|
259
|
+
def action_help(self) -> None:
|
|
260
|
+
"""Show help information."""
|
|
261
|
+
help_text = """
|
|
262
|
+
Navigation:
|
|
263
|
+
- ↑↓: Navigate tree
|
|
264
|
+
- Enter: Expand/collapse node
|
|
265
|
+
- /: Focus search
|
|
266
|
+
- c: Copy command to clipboard
|
|
267
|
+
- r: Run command directly (no args)
|
|
268
|
+
- b: Build command with arguments
|
|
269
|
+
- q: Quit
|
|
270
|
+
- ?: Show this help
|
|
271
|
+
"""
|
|
272
|
+
self.notify(help_text, severity="information", timeout=10)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Search bar widget for filtering commands.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from textual.app import ComposeResult
|
|
6
|
+
from textual.containers import Horizontal
|
|
7
|
+
from textual.widgets import Label, Input
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SearchBar(Horizontal):
|
|
11
|
+
"""Search bar widget."""
|
|
12
|
+
|
|
13
|
+
def compose(self) -> ComposeResult:
|
|
14
|
+
yield Label("🔍 Search: ", classes="search-label")
|
|
15
|
+
yield Input(placeholder="Type to search commands...", id="search-input")
|
|
File without changes
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
|
|
2
|
+
from typing import cast, Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_all_ipv4_addresses() -> list[tuple[str, str]]:
|
|
6
|
+
import psutil
|
|
7
|
+
import socket
|
|
8
|
+
result: list[tuple[str, str]] = []
|
|
9
|
+
for iface, addrs in psutil.net_if_addrs().items():
|
|
10
|
+
for addr in addrs:
|
|
11
|
+
if addr.family == socket.AF_INET:
|
|
12
|
+
ip = addr.address
|
|
13
|
+
result.append((iface, ip))
|
|
14
|
+
return result
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def select_lan_ipv4(prefer_vpn: bool) -> Optional[str]:
|
|
18
|
+
"""
|
|
19
|
+
Choose the best 'real LAN' IPv4:
|
|
20
|
+
- Excludes loopback/link-local and (by default) VPN/tunnel/container ifaces
|
|
21
|
+
- Prefers physical-looking ifaces (eth/en*/wlan/wl*)
|
|
22
|
+
- Prefers RFC1918 LANs: 192.168/16 > 10/8 > 172.16/12
|
|
23
|
+
- Requires interface is UP
|
|
24
|
+
Set prefer_vpn=True to allow tunnel/VPN ifaces to compete.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import ipaddress
|
|
28
|
+
import re
|
|
29
|
+
from collections.abc import Sequence
|
|
30
|
+
import psutil
|
|
31
|
+
|
|
32
|
+
# Down-rank or exclude: tunnels/VPNs/bridges/containers (add your own if needed)
|
|
33
|
+
VIRTUAL_IFACE_PAT = re.compile(
|
|
34
|
+
r"^(?:lo|loopback|docker\d*|br-.*|veth.*|virbr.*|bridge.*|"
|
|
35
|
+
r"vboxnet.*|vmnet.*|zt.*|ham.*|tailscale.*|wg\d*|utun\d*|llw\d*|awdl\d*|"
|
|
36
|
+
r"tun\d*|tap\d*|cloudflarewarp.*|warp.*)$",
|
|
37
|
+
re.IGNORECASE,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Light preference for names that look like real NICs
|
|
41
|
+
PHYSICAL_IFACE_PAT = re.compile(
|
|
42
|
+
r"^(?:eth\d*|en\d*|enp.*|ens.*|eno.*|wlan\d*|wl.*|.*wifi.*|.*ethernet.*)$",
|
|
43
|
+
re.IGNORECASE,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Known noisy CIDRs to avoid
|
|
47
|
+
NOISY_NETS: list[ipaddress.IPv4Network] = [
|
|
48
|
+
ipaddress.IPv4Network("100.64.0.0/10"), # CGNAT (Tailscale/others)
|
|
49
|
+
ipaddress.IPv4Network("172.17.0.0/16"), # docker0 default
|
|
50
|
+
ipaddress.IPv4Network("172.18.0.0/16"),
|
|
51
|
+
ipaddress.IPv4Network("172.19.0.0/16"),
|
|
52
|
+
ipaddress.IPv4Network("192.168.49.0/24"), # minikube default
|
|
53
|
+
ipaddress.IPv4Network("10.0.2.0/24"), # VirtualBox NAT
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
def _in_any(ip: ipaddress.IPv4Address, nets: Sequence[ipaddress.IPv4Network]) -> bool:
|
|
57
|
+
return any(ip in n for n in nets)
|
|
58
|
+
|
|
59
|
+
stats = psutil.net_if_stats()
|
|
60
|
+
best = None
|
|
61
|
+
best_score = -10**9
|
|
62
|
+
import socket
|
|
63
|
+
for iface, addrs in psutil.net_if_addrs().items():
|
|
64
|
+
st = stats.get(iface)
|
|
65
|
+
if not st or not st.isup:
|
|
66
|
+
continue
|
|
67
|
+
|
|
68
|
+
for a in addrs:
|
|
69
|
+
if a.family != socket.AF_INET or not a.address:
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
ip_str = a.address
|
|
73
|
+
try:
|
|
74
|
+
ip = cast(ipaddress.IPv4Address, ipaddress.ip_address(ip_str))
|
|
75
|
+
except ValueError:
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
# Exclude unusable classes
|
|
79
|
+
if ip.is_loopback or ip.is_link_local: # 127.0.0.0/8, 169.254.0.0/16
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
# Hard filter: if it looks virtual and we don't prefer VPNs, skip it
|
|
83
|
+
if not prefer_vpn and VIRTUAL_IFACE_PAT.match(iface):
|
|
84
|
+
continue
|
|
85
|
+
|
|
86
|
+
# Hard filter: known noisy subnets (docker, cgnat, etc.)
|
|
87
|
+
if _in_any(ip, NOISY_NETS) and not prefer_vpn:
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
# Base score
|
|
91
|
+
score = 0
|
|
92
|
+
|
|
93
|
+
# Prefer physical-looking names
|
|
94
|
+
if PHYSICAL_IFACE_PAT.match(iface):
|
|
95
|
+
score += 200
|
|
96
|
+
|
|
97
|
+
# Broadcast present usually means L2 LAN (not point-to-point)
|
|
98
|
+
# (psutil puts it on the same entry as .broadcast)
|
|
99
|
+
if getattr(a, "broadcast", None):
|
|
100
|
+
score += 100
|
|
101
|
+
|
|
102
|
+
# Prefer private RFC1918; rank families
|
|
103
|
+
if ip.is_private:
|
|
104
|
+
# Order: 192.168.x.x > 10.x.x.x > 172.16-31.x.x
|
|
105
|
+
ip_net = ipaddress.IPv4Network((ip, 32), strict=False)
|
|
106
|
+
if ipaddress.IPv4Network("192.168.0.0/16").supernet_of(ip_net):
|
|
107
|
+
score += 90
|
|
108
|
+
elif ipaddress.IPv4Network("10.0.0.0/8").supernet_of(ip_net):
|
|
109
|
+
score += 70
|
|
110
|
+
elif ipaddress.IPv4Network("172.16.0.0/12").supernet_of(ip_net):
|
|
111
|
+
score += 50
|
|
112
|
+
else:
|
|
113
|
+
# Public on a NIC is unusual for a home/office LAN
|
|
114
|
+
score -= 50
|
|
115
|
+
|
|
116
|
+
# Slight nudge by interface speed if known (>0 means psutil knows it)
|
|
117
|
+
# (Many tunnels report 0)
|
|
118
|
+
if getattr(st, "speed", 0) > 0:
|
|
119
|
+
score += 20
|
|
120
|
+
|
|
121
|
+
# Deterministic tie-breaker: prefer shorter iface name (eth0 over eth10)
|
|
122
|
+
score -= len(iface) * 0.01
|
|
123
|
+
|
|
124
|
+
if score > best_score:
|
|
125
|
+
best_score = score
|
|
126
|
+
best = ip_str
|
|
127
|
+
|
|
128
|
+
return best
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
print(select_lan_ipv4(False) or "No LAN IPv4 found")
|
machineconfig/scripts/python/{devops_add_identity.py → helpers_network/devops_add_identity.py}
RENAMED
|
@@ -12,9 +12,7 @@ BOX_WIDTH = 150 # width for box drawing
|
|
|
12
12
|
def main() -> None:
|
|
13
13
|
title = "🔑 SSH IDENTITY MANAGEMENT"
|
|
14
14
|
print(Panel(Text(title, justify="center"), expand=False))
|
|
15
|
-
|
|
16
15
|
print(Panel("🔍 Searching for existing SSH keys...", expand=False))
|
|
17
|
-
|
|
18
16
|
private_keys = [x.with_name(x.stem) for x in PathExtended.home().joinpath(".ssh").search("*.pub")]
|
|
19
17
|
private_keys = [x for x in private_keys if x.exists()]
|
|
20
18
|
if private_keys:
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""SSH"""
|
|
2
|
+
|
|
3
|
+
from platform import system
|
|
4
|
+
from machineconfig.utils.source_of_truth import LIBRARY_ROOT
|
|
5
|
+
from machineconfig.utils.path_extended import PathExtended
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.panel import Panel
|
|
8
|
+
from rich import box
|
|
9
|
+
from typing import Optional, Annotated
|
|
10
|
+
import typer
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
console = Console()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_add_ssh_key_script(path_to_key: PathExtended) -> str:
|
|
17
|
+
console.print(Panel("🔑 SSH KEY CONFIGURATION", title="[bold blue]SSH Setup[/bold blue]"))
|
|
18
|
+
if system() == "Linux" or system() == "Darwin":
|
|
19
|
+
authorized_keys = PathExtended.home().joinpath(".ssh/authorized_keys")
|
|
20
|
+
console.print(Panel(f"🐧 Linux SSH configuration\n📄 Authorized keys file: {authorized_keys}", title="[bold blue]System Info[/bold blue]"))
|
|
21
|
+
elif system() == "Windows":
|
|
22
|
+
authorized_keys = PathExtended("C:/ProgramData/ssh/administrators_authorized_keys")
|
|
23
|
+
console.print(Panel(f"🪟 Windows SSH configuration\n📄 Authorized keys file: {authorized_keys}", title="[bold blue]System Info[/bold blue]"))
|
|
24
|
+
else:
|
|
25
|
+
console.print(Panel("❌ ERROR: Unsupported operating system\nOnly Linux and Windows are supported", title="[bold red]Error[/bold red]"))
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
|
|
28
|
+
if authorized_keys.exists():
|
|
29
|
+
split = "\n"
|
|
30
|
+
keys_text = authorized_keys.read_text(encoding="utf-8").split(split)
|
|
31
|
+
key_count = len([k for k in keys_text if k.strip()])
|
|
32
|
+
console.print(Panel(f"🔍 Current SSH authorization status\n✅ Found {key_count} authorized key(s)", title="[bold blue]Status[/bold blue]"))
|
|
33
|
+
if path_to_key.read_text(encoding="utf-8") in authorized_keys.read_text(encoding="utf-8"):
|
|
34
|
+
console.print(Panel(f"⚠️ Key already authorized\nKey: {path_to_key.name}\nStatus: Already present in authorized_keys file\nNo action required", title="[bold yellow]Warning[/bold yellow]"))
|
|
35
|
+
program = ""
|
|
36
|
+
else:
|
|
37
|
+
console.print(Panel(f"➕ Adding new SSH key to authorized keys\n🔑 Key file: {path_to_key.name}", title="[bold blue]Action[/bold blue]"))
|
|
38
|
+
if system() == "Linux" or system() == "Darwin":
|
|
39
|
+
program = f"cat {path_to_key} >> ~/.ssh/authorized_keys"
|
|
40
|
+
elif system() == "Windows":
|
|
41
|
+
program_path = LIBRARY_ROOT.joinpath("setup_windows/add-sshkey.ps1")
|
|
42
|
+
program = program_path.expanduser().read_text(encoding="utf-8")
|
|
43
|
+
place_holder = r'$sshfile = "$env:USERPROFILE\.ssh\pubkey.pub"'
|
|
44
|
+
assert place_holder in program, f"This section performs string manipulation on the script {program_path} to add the key to the authorized_keys file. The script has changed and the string {place_holder} is not found."
|
|
45
|
+
program = program.replace(place_holder, f'$sshfile = "{path_to_key}"')
|
|
46
|
+
console.print(Panel("🔧 Configured PowerShell script for Windows\n📝 Replaced placeholder with actual key path", title="[bold blue]Configuration[/bold blue]"))
|
|
47
|
+
else:
|
|
48
|
+
raise NotImplementedError
|
|
49
|
+
else:
|
|
50
|
+
console.print(Panel(f"📝 Creating new authorized_keys file\n🔑 Using key: {path_to_key.name}", title="[bold blue]Action[/bold blue]"))
|
|
51
|
+
if system() == "Linux" or system() == "Darwin":
|
|
52
|
+
program = f"cat {path_to_key} > ~/.ssh/authorized_keys"
|
|
53
|
+
else:
|
|
54
|
+
program_path = LIBRARY_ROOT.joinpath("setup_windows/openssh-server_add-sshkey.ps1")
|
|
55
|
+
program = PathExtended(program_path).expanduser().read_text(encoding="utf-8").replace('$sshfile=""', f'$sshfile="{path_to_key}"')
|
|
56
|
+
console.print(Panel("🔧 Configured PowerShell script for Windows\n📝 Set key path in script", title="[bold blue]Configuration[/bold blue]"))
|
|
57
|
+
|
|
58
|
+
if system() == "Linux" or system() == "Darwin":
|
|
59
|
+
program += """
|
|
60
|
+
sudo chmod 700 ~/.ssh
|
|
61
|
+
sudo chmod 644 ~/.ssh/authorized_keys
|
|
62
|
+
sudo chmod 644 ~/.ssh/*.pub
|
|
63
|
+
sudo service ssh --full-restart
|
|
64
|
+
# from superuser.com/questions/215504/permissions-on-private-key-in-ssh-folder
|
|
65
|
+
"""
|
|
66
|
+
return program
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
Common pitfalls:
|
|
71
|
+
🚫 Wrong line endings (LF/CRLF) in config files
|
|
72
|
+
🌐 Network port conflicts (try 2222 -> 2223) between WSL and Windows
|
|
73
|
+
sudo service ssh restart
|
|
74
|
+
sudo service ssh status
|
|
75
|
+
sudo nano /etc/ssh/sshd_config
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def main(pub_path: Annotated[Optional[str], typer.Argument(..., help="Path to the public key file")] = None,
|
|
80
|
+
pub_choose: Annotated[bool, typer.Option(..., "--choose", "-c", help="Choose from available public keys in ~/.ssh")] = False,
|
|
81
|
+
pub_val: Annotated[bool, typer.Option(..., "--paste", "-p", help="Paste the public key content manually")] = False,
|
|
82
|
+
from_github: Annotated[Optional[str], typer.Option(..., "--from-github", "-g", help="Fetch public keys from a GitHub username")] = None
|
|
83
|
+
) -> None:
|
|
84
|
+
|
|
85
|
+
if pub_path:
|
|
86
|
+
key_path = PathExtended(pub_path).expanduser().absolute()
|
|
87
|
+
key_path.parent.mkdir(parents=True, exist_ok=True)
|
|
88
|
+
if not key_path.exists():
|
|
89
|
+
console.print(Panel(f"❌ ERROR: Provided key path does not exist\nPath: {key_path}", title="[bold red]Error[/bold red]"))
|
|
90
|
+
raise FileNotFoundError(f"Provided key path does not exist: {key_path}")
|
|
91
|
+
console.print(Panel(f"📄 Using provided public key file: {key_path}", title="[bold blue]Info[/bold blue]"))
|
|
92
|
+
program = get_add_ssh_key_script(key_path)
|
|
93
|
+
from machineconfig.utils.code import run_shell_script
|
|
94
|
+
run_shell_script(script=program)
|
|
95
|
+
console.print(Panel("✅ SSH KEY AUTHORIZATION COMPLETED", box=box.DOUBLE_EDGE, title_align="left"))
|
|
96
|
+
return
|
|
97
|
+
elif pub_choose:
|
|
98
|
+
console.print(Panel("🔐 SSH PUBLIC KEY AUTHORIZATION TOOL", box=box.DOUBLE_EDGE, title_align="left"))
|
|
99
|
+
console.print(Panel("🔍 Searching for public keys...", title="[bold blue]SSH Setup[/bold blue]", border_style="blue"))
|
|
100
|
+
pub_keys = PathExtended.home().joinpath(".ssh").search("*.pub")
|
|
101
|
+
if pub_keys:
|
|
102
|
+
console.print(Panel(f"✅ Found {len(pub_keys)} public key(s)", title="[bold green]Status[/bold green]", border_style="green"))
|
|
103
|
+
else:
|
|
104
|
+
console.print(Panel("⚠️ No public keys found", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
|
|
105
|
+
return
|
|
106
|
+
console.print(Panel(f"🔄 Processing all {len(pub_keys)} public keys...", title="[bold blue]Processing[/bold blue]", border_style="blue"))
|
|
107
|
+
program = "\n\n\n".join([get_add_ssh_key_script(key) for key in pub_keys])
|
|
108
|
+
|
|
109
|
+
elif pub_val:
|
|
110
|
+
console.print(Panel("📋 Please provide a filename and paste the public key content", title="[bold blue]Input Required[/bold blue]", border_style="blue"))
|
|
111
|
+
key_filename = input("📝 File name (default: my_pasted_key.pub): ") or "my_pasted_key.pub"
|
|
112
|
+
key_path = PathExtended.home().joinpath(f".ssh/{key_filename}")
|
|
113
|
+
key_path.parent.mkdir(parents=True, exist_ok=True)
|
|
114
|
+
key_path.write_text(input("🔑 Paste the public key here: "), encoding="utf-8")
|
|
115
|
+
console.print(Panel(f"💾 Key saved to: {key_path}", title="[bold green]Success[/bold green]", border_style="green"))
|
|
116
|
+
program = get_add_ssh_key_script(key_path)
|
|
117
|
+
elif from_github:
|
|
118
|
+
console.print(Panel(f"🌐 Fetching public keys from GitHub user: {from_github}", title="[bold blue]GitHub Fetch[/bold blue]", border_style="blue"))
|
|
119
|
+
import requests
|
|
120
|
+
response = requests.get(f"https://api.github.com/users/{from_github}/keys")
|
|
121
|
+
if response.status_code != 200:
|
|
122
|
+
console.print(Panel(f"❌ ERROR: Failed to fetch keys from GitHub user {from_github}\nStatus Code: {response.status_code}", title="[bold red]Error[/bold red]", border_style="red"))
|
|
123
|
+
raise RuntimeError(f"Failed to fetch keys from GitHub user {from_github}: Status Code {response.status_code}")
|
|
124
|
+
keys = response.json()
|
|
125
|
+
if not keys:
|
|
126
|
+
console.print(Panel(f"⚠️ No public keys found for GitHub user: {from_github}", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
|
|
127
|
+
return
|
|
128
|
+
console.print(Panel(f"✅ Found {len(keys)} public key(s) for user: {from_github}", title="[bold green]Success[/bold green]", border_style="green"))
|
|
129
|
+
key_path = PathExtended.home().joinpath(f".ssh/{from_github}_github_keys.pub")
|
|
130
|
+
key_path.parent.mkdir(parents=True, exist_ok=True)
|
|
131
|
+
key_path.write_text("\n".join([key["key"] for key in keys]), encoding="utf-8")
|
|
132
|
+
console.print(Panel(f"💾 Keys saved to: {key_path}", title="[bold green]Success[/bold green]", border_style="green"))
|
|
133
|
+
program = get_add_ssh_key_script(key_path)
|
|
134
|
+
else:
|
|
135
|
+
console.print(Panel("❌ ERROR: No method provided to add SSH key\nUse --help for options", title="[bold red]Error[/bold red]", border_style="red"))
|
|
136
|
+
raise ValueError("No method provided to add SSH key. Use --help for options.")
|
|
137
|
+
console.print(Panel("🚀 SSH KEY AUTHORIZATION READY\nRun the generated script to apply changes", box=box.DOUBLE_EDGE, title_align="left"))
|
|
138
|
+
from machineconfig.utils.code import run_shell_script
|
|
139
|
+
run_shell_script(script=program)
|
|
140
|
+
|
|
141
|
+
import machineconfig.scripts.python.helpers_network.address as helper
|
|
142
|
+
res = helper.select_lan_ipv4(prefer_vpn=False)
|
|
143
|
+
if res is None:
|
|
144
|
+
console.print(Panel("❌ ERROR: Could not determine local LAN IPv4 address", title="[bold red]Error[/bold red]", border_style="red"))
|
|
145
|
+
raise typer.Exit(code=1)
|
|
146
|
+
local_ip_v4 = res
|
|
147
|
+
|
|
148
|
+
console.print(Panel(f"🌐 This computer is accessible at: {local_ip_v4}", title="[bold green]Network Info[/bold green]", border_style="green"))
|
|
149
|
+
console.print(Panel("✅ SSH KEY AUTHORIZATION COMPLETED", box=box.DOUBLE_EDGE, title_align="left"))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
if __name__ == "__main__":
|
|
153
|
+
pass
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
# mkdir ~/data/local
|
|
6
6
|
# sudo mount -o nolock,noatime,nodiratime,proto=tcp,timeo=600,retrans=2,noac alex-p51s-5:/home/alex/data/local ./data/local
|
|
7
7
|
|
|
8
|
-
uv run --python 3.13 --no-dev --project $HOME/code/machineconfig python -m machineconfig.scripts.python.mount_nfs
|
|
9
8
|
# Check if remote server is reachable and share folder exists
|
|
10
9
|
if ! ping -c 1 "$remote_server" &> /dev/null; then
|
|
11
10
|
echo "💥 Error: Remote server $remote_server is not reachable."
|
|
@@ -19,9 +19,9 @@ def main():
|
|
|
19
19
|
print("\n🔍 Interactive mode selected for choosing share path.")
|
|
20
20
|
tmp = choose_ssh_host(multi=False)
|
|
21
21
|
assert isinstance(tmp, str)
|
|
22
|
-
ssh = SSH(tmp)
|
|
23
|
-
default = f"{ssh.hostname}:{ssh.
|
|
24
|
-
share_info = choose_from_options(msg="📂 Choose a share path:", options=[f"{ssh.hostname}:{item.split(' ')[0]}" for item in ssh.
|
|
22
|
+
ssh = SSH(host=tmp, username=None, hostname=None, ssh_key_path=None, password=None, port=22, enable_compression=False)
|
|
23
|
+
default = f"{ssh.hostname}:{ssh.run_shell_cmd_on_remote(command='echo $HOME', verbose_output=False, description='Get home directory', strict_stderr=False, strict_return_code=True).op}/data/share_nfs"
|
|
24
|
+
share_info = choose_from_options(msg="📂 Choose a share path:", options=[f"{ssh.hostname}:{item.split(' ')[0]}" for item in ssh.run_shell_cmd_on_remote(command="cat /etc/exports", verbose_output=False, description='Get NFS exports', strict_stderr=False, strict_return_code=False).op.split("\n") if not item.startswith("#")] + [default], default=default, multi=False)
|
|
25
25
|
assert isinstance(share_info, str), f"❌ share_info must be a string. Got {type(share_info)}"
|
|
26
26
|
|
|
27
27
|
remote_server = share_info.split(":")[0]
|
|
@@ -17,8 +17,7 @@ drive_location=''
|
|
|
17
17
|
mount_point=''
|
|
18
18
|
username=''
|
|
19
19
|
password=''
|
|
20
|
-
|
|
21
|
-
uv run --PYTHON 3.13 --no-dev --project $HOME/code/machineconfig python -m machineconfig.scripts.python.mount_nw_drive
|
|
20
|
+
machineconfig.scripts.python.mount_nw_drive
|
|
22
21
|
|
|
23
22
|
# Check if mount point directory exists, create if not
|
|
24
23
|
if [ ! -d "$mount_point" ]; then
|
|
@@ -18,10 +18,10 @@ def main():
|
|
|
18
18
|
print("\n🔍 Interactive mode selected for choosing share path.")
|
|
19
19
|
tmp = choose_ssh_host(multi=False)
|
|
20
20
|
assert isinstance(tmp, str)
|
|
21
|
-
ssh = SSH(host=tmp)
|
|
22
|
-
share_info = f"{ssh.username}@{ssh.hostname}:{ssh.
|
|
21
|
+
ssh = SSH(host=tmp, username=None, hostname=None, ssh_key_path=None, password=None, port=22, enable_compression=False)
|
|
22
|
+
share_info = f"{ssh.username}@{ssh.hostname}:{ssh.run_shell_cmd_on_remote(command='echo $HOME', verbose_output=False, description='Get home directory', strict_stderr=False, strict_return_code=True).op}/data/share_ssh"
|
|
23
23
|
else:
|
|
24
|
-
ssh = SSH(share_info.split(":")[0])
|
|
24
|
+
ssh = SSH(host=share_info.split(":")[0], username=None, hostname=None, ssh_key_path=None, password=None, port=22, enable_compression=False)
|
|
25
25
|
|
|
26
26
|
print(f"\n🌐 Share Info: {share_info}")
|
|
27
27
|
|