machineconfig 7.50__py3-none-any.whl → 8.12__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.
Potentially problematic release.
This version of machineconfig might be problematic. Click here for more details.
- machineconfig/cluster/remote/cloud_manager.py +1 -1
- machineconfig/cluster/sessions_managers/utils/maker.py +23 -11
- machineconfig/cluster/sessions_managers/wt_local_manager.py +22 -19
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +3 -1
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +3 -1
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +2 -2
- machineconfig/jobs/installer/installer_data.json +1185 -165
- machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
- machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
- machineconfig/jobs/installer/package_groups.py +52 -84
- machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
- machineconfig/jobs/installer/{custom → python_scripts}/boxes.py +2 -2
- machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
- machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +4 -1
- machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
- machineconfig/jobs/installer/{custom → python_scripts}/hx.py +16 -12
- machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
- machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +27 -22
- machineconfig/jobs/installer/python_scripts/sysabc.py +139 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
- machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
- machineconfig/jobs/installer/python_scripts/yazi.py +121 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
- machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
- machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
- machineconfig/jobs/scripts_dynamic/a.py +25 -0
- machineconfig/logger.py +0 -1
- machineconfig/profile/create_helper.py +21 -22
- machineconfig/profile/create_links_export.py +25 -11
- machineconfig/profile/create_shell_profile.py +14 -3
- machineconfig/profile/mapper.toml +8 -6
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/linux/wrap_mcfg +20 -21
- machineconfig/scripts/python/agents.py +74 -50
- machineconfig/scripts/python/ai/initai.py +1 -1
- machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
- machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +1 -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 +4 -0
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
- machineconfig/scripts/python/ai/solutions/generic.py +1 -1
- machineconfig/scripts/python/ai/{generate_files.py → utils/generate_files.py} +2 -2
- machineconfig/scripts/python/cloud.py +6 -6
- machineconfig/scripts/python/croshell.py +67 -60
- machineconfig/scripts/python/devops.py +41 -21
- machineconfig/scripts/python/devops_navigator.py +0 -4
- machineconfig/scripts/python/env_manager/env_manager_tui.py +204 -0
- machineconfig/scripts/python/env_manager/path_manager_tui.py +1 -1
- machineconfig/scripts/python/fire_jobs.py +95 -67
- machineconfig/scripts/python/ftpx.py +44 -17
- 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/symantic_search.py +25 -0
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +1 -1
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +9 -7
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +21 -8
- machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +0 -12
- machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +30 -11
- machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +9 -2
- machineconfig/scripts/python/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
- machineconfig/scripts/python/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
- machineconfig/scripts/python/helpers_agents/privacy/configs/copilot/config.yml +1 -0
- machineconfig/scripts/python/helpers_agents/privacy/configs/crush/crush.json +10 -0
- machineconfig/scripts/python/helpers_agents/privacy/configs/gemini/settings.json +12 -0
- machineconfig/scripts/python/helpers_agents/privacy/privacy.py +109 -0
- machineconfig/scripts/python/helpers_agents/templates/prompt.txt +8 -4
- machineconfig/scripts/python/helpers_agents/templates/template.sh +18 -8
- machineconfig/scripts/python/helpers_cloud/cloud_copy.py +28 -21
- machineconfig/scripts/python/helpers_cloud/cloud_helpers.py +1 -1
- machineconfig/scripts/python/helpers_cloud/cloud_mount.py +19 -17
- machineconfig/scripts/python/helpers_cloud/cloud_sync.py +8 -7
- machineconfig/scripts/python/helpers_croshell/crosh.py +3 -3
- machineconfig/scripts/python/helpers_croshell/start_slidev.py +6 -7
- machineconfig/scripts/python/helpers_devops/cli_config.py +19 -25
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +22 -13
- machineconfig/scripts/python/helpers_devops/cli_nw.py +113 -26
- machineconfig/scripts/python/helpers_devops/cli_repos.py +37 -11
- machineconfig/scripts/python/helpers_devops/cli_self.py +84 -39
- machineconfig/scripts/python/helpers_devops/cli_share_file.py +9 -9
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +13 -12
- machineconfig/scripts/python/helpers_devops/{cli_terminal.py → cli_share_terminal.py} +15 -17
- machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +4 -4
- machineconfig/scripts/python/helpers_devops/devops_status.py +7 -19
- machineconfig/scripts/python/helpers_devops/run_script.py +168 -0
- machineconfig/scripts/python/helpers_devops/themes/choose_wezterm_theme.py +1 -1
- machineconfig/scripts/python/helpers_fire_command/file_wrangler.py +2 -19
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_args_helper.py +1 -0
- machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +25 -15
- machineconfig/scripts/python/helpers_msearch/scripts_linux/fzfg +3 -3
- machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfg.ps1 +58 -1
- machineconfig/scripts/python/helpers_navigator/command_tree.py +50 -18
- machineconfig/scripts/python/helpers_network/address.py +176 -0
- machineconfig/scripts/python/helpers_network/address_switch.py +78 -0
- machineconfig/scripts/python/{nw → helpers_network}/mount_nfs.py +2 -2
- machineconfig/scripts/python/{nw → helpers_network}/mount_ssh.py +1 -1
- machineconfig/scripts/python/{nw/devops_add_identity.py → helpers_network/ssh_add_identity.py} +35 -1
- machineconfig/scripts/python/{nw/devops_add_ssh_key.py → helpers_network/ssh_add_ssh_key.py} +26 -7
- machineconfig/scripts/python/{nw → helpers_network}/ssh_debug_linux.py +7 -7
- machineconfig/scripts/python/{nw → helpers_network}/ssh_debug_windows.py +4 -4
- machineconfig/scripts/python/helpers_repos/clone.py +0 -1
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +13 -5
- machineconfig/scripts/python/helpers_repos/entrypoint.py +2 -1
- machineconfig/scripts/python/helpers_repos/record.py +2 -1
- machineconfig/scripts/python/helpers_repos/repo_analyzer_1.py +160 -0
- machineconfig/scripts/python/helpers_repos/{count_lines.py → repo_analyzer_2.py} +113 -192
- machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +19 -13
- machineconfig/scripts/python/helpers_utils/download.py +150 -0
- machineconfig/scripts/python/helpers_utils/pdf.py +96 -0
- machineconfig/scripts/python/helpers_utils/python.py +187 -0
- machineconfig/scripts/python/interactive.py +17 -26
- machineconfig/scripts/python/{machineconfig.py → mcfg_entry.py} +4 -5
- machineconfig/scripts/python/msearch.py +57 -6
- machineconfig/scripts/python/sessions.py +100 -31
- machineconfig/scripts/python/terminal.py +26 -17
- machineconfig/scripts/python/utils.py +17 -15
- machineconfig/scripts/windows/wrap_mcfg.ps1 +6 -3
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/linters/.ruff.toml +1 -1
- machineconfig/settings/shells/bash/init.sh +29 -2
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
- machineconfig/settings/shells/nushell/config.nu +2 -2
- machineconfig/settings/shells/nushell/env.nu +45 -6
- machineconfig/settings/shells/nushell/init.nu +282 -95
- machineconfig/settings/shells/pwsh/init.ps1 +1 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
- machineconfig/settings/shells/zsh/init.sh +1 -8
- 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/wt/__init__.py +0 -0
- machineconfig/settings/yazi/init.lua +49 -24
- machineconfig/settings/yazi/keymap_linux.toml +19 -4
- machineconfig/settings/yazi/keymap_windows.toml +0 -1
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +29 -5
- machineconfig/settings/yazi/theme.toml +4 -0
- machineconfig/settings/yazi/yazi_linux.toml +84 -0
- machineconfig/settings/yazi/yazi_windows.toml +58 -0
- machineconfig/settings/zellij/layouts/st.kdl +39 -8
- machineconfig/setup_linux/__init__.py +1 -2
- machineconfig/setup_linux/apps_desktop.sh +8 -27
- machineconfig/setup_linux/web_shortcuts/interactive.sh +12 -10
- machineconfig/setup_linux/web_shortcuts/live_from_github.sh +31 -0
- machineconfig/setup_mac/__init__.py +2 -3
- machineconfig/setup_windows/__init__.py +3 -5
- machineconfig/setup_windows/ssh/openssh-server.ps1 +1 -1
- machineconfig/setup_windows/uv.ps1 +8 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +12 -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 -4
- machineconfig/utils/code.py +39 -11
- machineconfig/utils/files/headers.py +2 -2
- 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 +43 -100
- 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} +36 -85
- machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +16 -59
- machineconfig/utils/io.py +0 -1
- machineconfig/utils/links.py +2 -2
- machineconfig/utils/meta.py +30 -16
- machineconfig/utils/options.py +42 -24
- machineconfig/utils/options_tv.py +119 -0
- machineconfig/utils/path_extended.py +42 -20
- machineconfig/utils/path_helper.py +75 -22
- machineconfig/utils/procs.py +1 -1
- machineconfig/utils/scheduler.py +20 -53
- machineconfig/utils/schemas/layouts/layout_types.py +1 -1
- machineconfig/utils/ssh.py +159 -418
- 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 +303 -0
- machineconfig/utils/ssh_utils/utils.py +142 -0
- machineconfig/utils/ssh_utils/wsl.py +210 -0
- machineconfig/utils/terminal.py +1 -0
- machineconfig/utils/upgrade_packages.py +6 -1
- machineconfig/utils/ve.py +12 -4
- machineconfig-8.12.dist-info/METADATA +132 -0
- {machineconfig-7.50.dist-info → machineconfig-8.12.dist-info}/RECORD +265 -215
- {machineconfig-7.50.dist-info → machineconfig-8.12.dist-info}/entry_points.txt +2 -4
- machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
- machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
- machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
- machineconfig/jobs/installer/powershell_scripts/openssh-server_add_key.ps1 +0 -7
- machineconfig/jobs/installer/powershell_scripts/openssh-server_copy-ssh-id.ps1 +0 -14
- machineconfig/scripts/linux/other/switch_ip +0 -20
- machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
- machineconfig/scripts/python/define.py +0 -31
- machineconfig/scripts/python/explore.py +0 -49
- machineconfig/scripts/python/helpers_devops/cli_utils.py +0 -246
- machineconfig/scripts/python/helpers_msearch/scripts_linux/fzfag +0 -17
- machineconfig/scripts/python/helpers_msearch/scripts_linux/fzfrga +0 -21
- machineconfig/scripts/python/helpers_msearch/scripts_linux/skrg +0 -4
- machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfb.ps1 +0 -3
- machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfrga.bat +0 -20
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +0 -17
- machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
- machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
- 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 -17
- machineconfig/setup_linux/apps.sh +0 -66
- machineconfig/setup_linux/others/cli_installation.sh +0 -137
- machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
- machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
- machineconfig/setup_mac/apps.sh +0 -73
- machineconfig/setup_windows/apps.ps1 +0 -62
- machineconfig/setup_windows/others/obs.ps1 +0 -4
- machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
- machineconfig/utils/installer_utils/installer.py +0 -221
- machineconfig-7.50.dist-info/METADATA +0 -92
- /machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
- /machineconfig/jobs/installer/{custom_dev → python_scripts}/__init__.py +0 -0
- /machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
- /machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
- /machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
- /machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
- /machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
- /machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
- /machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
- /machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
- /machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/android.sh +0 -0
- /machineconfig/jobs/{installer/linux_scripts → scripts/bash_scripts}/lid.sh +0 -0
- /machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/mint_keyboard_shortcuts.sh +0 -0
- /machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
- /machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
- /machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
- /machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
- /machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
- /machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
- /machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
- /machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
- /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
- /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
- /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
- /machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
- /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
- /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
- /machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
- /machineconfig/scripts/python/{nw → ai/utils}/__init__.py +0 -0
- /machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +0 -0
- /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers_fire_command/f.py} +0 -0
- /machineconfig/{setup_windows/wt_and_pwsh → scripts/python/helpers_network}/__init__.py +0 -0
- /machineconfig/scripts/python/{nw → helpers_network}/mount_nw_drive.py +0 -0
- /machineconfig/scripts/python/{nw → helpers_network}/onetimeshare.py +0 -0
- /machineconfig/scripts/python/{nw → helpers_network}/wifi_conn.py +0 -0
- /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
- {machineconfig-7.50.dist-info → machineconfig-8.12.dist-info}/WHEEL +0 -0
- {machineconfig-7.50.dist-info → machineconfig-8.12.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
|
|
2
|
+
from typing import Optional, TypedDict, cast
|
|
3
|
+
|
|
4
|
+
class CountryFlag(TypedDict, total=False):
|
|
5
|
+
emoji: str
|
|
6
|
+
unicode: str
|
|
7
|
+
|
|
8
|
+
class CountryCurrency(TypedDict, total=False):
|
|
9
|
+
code: str
|
|
10
|
+
symbol: str
|
|
11
|
+
|
|
12
|
+
class Continent(TypedDict, total=False):
|
|
13
|
+
code: str
|
|
14
|
+
name: str
|
|
15
|
+
|
|
16
|
+
class PublicIpInfo(TypedDict, total=True):
|
|
17
|
+
ip: str
|
|
18
|
+
hostname: str
|
|
19
|
+
city: str
|
|
20
|
+
region: str
|
|
21
|
+
country: str
|
|
22
|
+
country_name: str
|
|
23
|
+
country_flag: CountryFlag
|
|
24
|
+
country_flag_url: str
|
|
25
|
+
country_currency: CountryCurrency
|
|
26
|
+
continent: Continent
|
|
27
|
+
loc: str
|
|
28
|
+
org: str
|
|
29
|
+
postal: str
|
|
30
|
+
timezone: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_public_ip_address() -> PublicIpInfo:
|
|
34
|
+
from machineconfig.utils.installer_utils.installer_cli import install_if_missing
|
|
35
|
+
import subprocess
|
|
36
|
+
install_if_missing("ipinfo")
|
|
37
|
+
result = subprocess.run(
|
|
38
|
+
["ipinfo", "myip", "--json"],
|
|
39
|
+
check=True,
|
|
40
|
+
capture_output=True,
|
|
41
|
+
text=True,
|
|
42
|
+
encoding="utf-8",
|
|
43
|
+
)
|
|
44
|
+
import json
|
|
45
|
+
loaded_json: PublicIpInfo = json.loads(result.stdout)
|
|
46
|
+
return loaded_json
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_all_ipv4_addresses() -> list[tuple[str, str]]:
|
|
50
|
+
import psutil
|
|
51
|
+
import socket
|
|
52
|
+
result: list[tuple[str, str]] = []
|
|
53
|
+
for iface, addrs in psutil.net_if_addrs().items():
|
|
54
|
+
for addr in addrs:
|
|
55
|
+
if addr.family == socket.AF_INET:
|
|
56
|
+
ip = addr.address
|
|
57
|
+
result.append((iface, ip))
|
|
58
|
+
return result
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def select_lan_ipv4(prefer_vpn: bool) -> Optional[str]:
|
|
62
|
+
"""
|
|
63
|
+
Choose the best 'real LAN' IPv4:
|
|
64
|
+
- Excludes loopback/link-local and (by default) VPN/tunnel/container ifaces
|
|
65
|
+
- Prefers physical-looking ifaces (eth/en*/wlan/wl*)
|
|
66
|
+
- Prefers RFC1918 LANs: 192.168/16 > 10/8 > 172.16/12
|
|
67
|
+
- Requires interface is UP
|
|
68
|
+
Set prefer_vpn=True to allow tunnel/VPN ifaces to compete.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
import ipaddress
|
|
72
|
+
import re
|
|
73
|
+
from collections.abc import Sequence
|
|
74
|
+
import psutil
|
|
75
|
+
|
|
76
|
+
# Down-rank or exclude: tunnels/VPNs/bridges/containers (add your own if needed)
|
|
77
|
+
VIRTUAL_IFACE_PAT = re.compile(
|
|
78
|
+
r"^(?:lo|loopback|docker\d*|br-.*|veth.*|virbr.*|bridge.*|"
|
|
79
|
+
r"vboxnet.*|vmnet.*|zt.*|ham.*|tailscale.*|wg\d*|utun\d*|llw\d*|awdl\d*|"
|
|
80
|
+
r"tun\d*|tap\d*|cloudflarewarp.*|warp.*)$",
|
|
81
|
+
re.IGNORECASE,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Light preference for names that look like real NICs
|
|
85
|
+
PHYSICAL_IFACE_PAT = re.compile(
|
|
86
|
+
r"^(?:eth\d*|en\d*|enp.*|ens.*|eno.*|wlan\d*|wl.*|.*wifi.*|.*ethernet.*)$",
|
|
87
|
+
re.IGNORECASE,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Known noisy CIDRs to avoid
|
|
91
|
+
NOISY_NETS: list[ipaddress.IPv4Network] = [
|
|
92
|
+
ipaddress.IPv4Network("100.64.0.0/10"), # CGNAT (Tailscale/others)
|
|
93
|
+
ipaddress.IPv4Network("172.17.0.0/16"), # docker0 default
|
|
94
|
+
ipaddress.IPv4Network("172.18.0.0/16"),
|
|
95
|
+
ipaddress.IPv4Network("172.19.0.0/16"),
|
|
96
|
+
ipaddress.IPv4Network("192.168.49.0/24"), # minikube default
|
|
97
|
+
ipaddress.IPv4Network("10.0.2.0/24"), # VirtualBox NAT
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
def _in_any(ip: ipaddress.IPv4Address, nets: Sequence[ipaddress.IPv4Network]) -> bool:
|
|
101
|
+
return any(ip in n for n in nets)
|
|
102
|
+
|
|
103
|
+
stats = psutil.net_if_stats()
|
|
104
|
+
best = None
|
|
105
|
+
best_score = -10**9
|
|
106
|
+
import socket
|
|
107
|
+
for iface, addrs in psutil.net_if_addrs().items():
|
|
108
|
+
st = stats.get(iface)
|
|
109
|
+
if not st or not st.isup:
|
|
110
|
+
continue
|
|
111
|
+
|
|
112
|
+
for a in addrs:
|
|
113
|
+
if a.family != socket.AF_INET or not a.address:
|
|
114
|
+
continue
|
|
115
|
+
|
|
116
|
+
ip_str = a.address
|
|
117
|
+
try:
|
|
118
|
+
ip = cast(ipaddress.IPv4Address, ipaddress.ip_address(ip_str))
|
|
119
|
+
except ValueError:
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
# Exclude unusable classes
|
|
123
|
+
if ip.is_loopback or ip.is_link_local: # 127.0.0.0/8, 169.254.0.0/16
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
# Hard filter: if it looks virtual and we don't prefer VPNs, skip it
|
|
127
|
+
if not prefer_vpn and VIRTUAL_IFACE_PAT.match(iface):
|
|
128
|
+
continue
|
|
129
|
+
|
|
130
|
+
# Hard filter: known noisy subnets (docker, cgnat, etc.)
|
|
131
|
+
if _in_any(ip, NOISY_NETS) and not prefer_vpn:
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
# Base score
|
|
135
|
+
score = 0
|
|
136
|
+
|
|
137
|
+
# Prefer physical-looking names
|
|
138
|
+
if PHYSICAL_IFACE_PAT.match(iface):
|
|
139
|
+
score += 200
|
|
140
|
+
|
|
141
|
+
# Broadcast present usually means L2 LAN (not point-to-point)
|
|
142
|
+
# (psutil puts it on the same entry as .broadcast)
|
|
143
|
+
if getattr(a, "broadcast", None):
|
|
144
|
+
score += 100
|
|
145
|
+
|
|
146
|
+
# Prefer private RFC1918; rank families
|
|
147
|
+
if ip.is_private:
|
|
148
|
+
# Order: 192.168.x.x > 10.x.x.x > 172.16-31.x.x
|
|
149
|
+
ip_net = ipaddress.IPv4Network((ip, 32), strict=False)
|
|
150
|
+
if ipaddress.IPv4Network("192.168.0.0/16").supernet_of(ip_net):
|
|
151
|
+
score += 90
|
|
152
|
+
elif ipaddress.IPv4Network("10.0.0.0/8").supernet_of(ip_net):
|
|
153
|
+
score += 70
|
|
154
|
+
elif ipaddress.IPv4Network("172.16.0.0/12").supernet_of(ip_net):
|
|
155
|
+
score += 50
|
|
156
|
+
else:
|
|
157
|
+
# Public on a NIC is unusual for a home/office LAN
|
|
158
|
+
score -= 50
|
|
159
|
+
|
|
160
|
+
# Slight nudge by interface speed if known (>0 means psutil knows it)
|
|
161
|
+
# (Many tunnels report 0)
|
|
162
|
+
if getattr(st, "speed", 0) > 0:
|
|
163
|
+
score += 20
|
|
164
|
+
|
|
165
|
+
# Deterministic tie-breaker: prefer shorter iface name (eth0 over eth10)
|
|
166
|
+
score -= len(iface) * 0.01
|
|
167
|
+
|
|
168
|
+
if score > best_score:
|
|
169
|
+
best_score = score
|
|
170
|
+
best = ip_str
|
|
171
|
+
|
|
172
|
+
return best
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
print(select_lan_ipv4(False) or "No LAN IPv4 found")
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from machineconfig.scripts.python.helpers_network.address import get_public_ip_address
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def switch_public_ip_address(max_trials: int = 10, wait_seconds: float = 4.0) -> None:
|
|
8
|
+
print("🔁 Switching IP ... ")
|
|
9
|
+
from machineconfig.utils.installer_utils.installer_cli import install_if_missing
|
|
10
|
+
install_if_missing("warp-cli")
|
|
11
|
+
|
|
12
|
+
current_ip: str | None = None
|
|
13
|
+
try:
|
|
14
|
+
current_data = get_public_ip_address()
|
|
15
|
+
current_ip = current_data.get("ip")
|
|
16
|
+
except Exception as e:
|
|
17
|
+
print(f"⚠️ Could not get current IP: {e}")
|
|
18
|
+
|
|
19
|
+
print(f"Current IP: {current_ip}")
|
|
20
|
+
|
|
21
|
+
for attempt in range(1, max_trials + 1):
|
|
22
|
+
print(f"\n--- Attempt {attempt}/{max_trials} ---")
|
|
23
|
+
|
|
24
|
+
print("🔻 Deactivating current connection ... ")
|
|
25
|
+
# We use check=False because if it's already deleted it might return non-zero
|
|
26
|
+
subprocess.run(["warp-cli", "registration", "delete"], check=False)
|
|
27
|
+
|
|
28
|
+
print(f"😴 Sleeping for {wait_seconds} seconds ... ")
|
|
29
|
+
time.sleep(wait_seconds)
|
|
30
|
+
|
|
31
|
+
print("🔼 Registering new connection ... ")
|
|
32
|
+
res_reg = subprocess.run(["warp-cli", "registration", "new"], check=False)
|
|
33
|
+
if res_reg.returncode != 0:
|
|
34
|
+
print("⚠️ Registration failed, retrying loop...")
|
|
35
|
+
continue
|
|
36
|
+
|
|
37
|
+
print("🔗 Connecting ... ")
|
|
38
|
+
subprocess.run(["warp-cli", "connect"], check=False)
|
|
39
|
+
|
|
40
|
+
print(f"😴 Sleeping for {wait_seconds} seconds ... ")
|
|
41
|
+
time.sleep(wait_seconds)
|
|
42
|
+
|
|
43
|
+
print("🔍 Checking status of warp ... ")
|
|
44
|
+
subprocess.run(["warp-cli", "status"], check=False)
|
|
45
|
+
|
|
46
|
+
print("🔍 Checking new IP ... ")
|
|
47
|
+
new_ip: str | None = None
|
|
48
|
+
# Retry getting IP a few times before giving up on this connection attempt
|
|
49
|
+
for ip_check_attempt in range(5):
|
|
50
|
+
try:
|
|
51
|
+
new_data = get_public_ip_address()
|
|
52
|
+
new_ip = new_data["ip"]
|
|
53
|
+
if new_ip:
|
|
54
|
+
break
|
|
55
|
+
except Exception as e:
|
|
56
|
+
print(f"⚠️ Error checking new IP (attempt {ip_check_attempt+1}/5): {e}")
|
|
57
|
+
time.sleep(wait_seconds)
|
|
58
|
+
|
|
59
|
+
if new_ip:
|
|
60
|
+
print(f"New IP: {new_ip}")
|
|
61
|
+
|
|
62
|
+
if current_ip and new_ip != current_ip:
|
|
63
|
+
print("✅ Done ... IP Changed.")
|
|
64
|
+
return
|
|
65
|
+
elif current_ip is None:
|
|
66
|
+
print("✅ Done ... IP obtained (was unknown).")
|
|
67
|
+
return
|
|
68
|
+
else:
|
|
69
|
+
print("❌ IP did not change.")
|
|
70
|
+
else:
|
|
71
|
+
print("⚠️ Could not retrieve new IP after multiple attempts.")
|
|
72
|
+
|
|
73
|
+
print("❌ Failed to switch IP after max trials.")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
switch_public_ip_address()
|
|
78
|
+
|
|
@@ -20,8 +20,8 @@ def main():
|
|
|
20
20
|
tmp = choose_ssh_host(multi=False)
|
|
21
21
|
assert isinstance(tmp, str)
|
|
22
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.
|
|
24
|
-
share_info = choose_from_options(msg="📂 Choose a share path:", options=[f"{ssh.hostname}:{item.split(' ')[0]}" for item in ssh.
|
|
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]
|
|
@@ -19,7 +19,7 @@ def main():
|
|
|
19
19
|
tmp = choose_ssh_host(multi=False)
|
|
20
20
|
assert isinstance(tmp, str)
|
|
21
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.
|
|
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
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
|
|
machineconfig/scripts/python/{nw/devops_add_identity.py → helpers_network/ssh_add_identity.py}
RENAMED
|
@@ -1,4 +1,38 @@
|
|
|
1
|
-
"""ID
|
|
1
|
+
"""ID
|
|
2
|
+
|
|
3
|
+
On windows:
|
|
4
|
+
|
|
5
|
+
# on the side of the local machine, you need to sort out the following:
|
|
6
|
+
# if the $sshfile doesn't have a standard name, you will need to explicitly specify the identity while SSHing (e.g. ssh u@s -i ~/.ssh/my_id)
|
|
7
|
+
# However, this must be done every time. For permanent solutions, use .ssh/config
|
|
8
|
+
$sshfile = "$env:USERPROFILE/.ssh/id_rsa"
|
|
9
|
+
Set-Service ssh-agent -StartupType Manual # allow the service to be started manually
|
|
10
|
+
ssh-agent # start the service
|
|
11
|
+
ssh-add.exe $sshfile # add the key to the agent
|
|
12
|
+
|
|
13
|
+
# add key:
|
|
14
|
+
$sshfile=""
|
|
15
|
+
$ErrorActionPreference = "Stop"
|
|
16
|
+
$sshd_dir = "$env:ProgramData/ssh"
|
|
17
|
+
cp "$sshd_dir/administrators_authorized_keys" "$sshd_dir/administrators_authorized_keys.orig"
|
|
18
|
+
Get-Content $sshfile >> "$sshd_dir/administrators_authorized_keys"
|
|
19
|
+
Restart-Service sshd -Force
|
|
20
|
+
|
|
21
|
+
# copy ssh key:
|
|
22
|
+
# This is the Windows equivalent of copy-ssh-id on Linux.
|
|
23
|
+
# Just like the original function, it is a convenient way of doing two things in one go:
|
|
24
|
+
# 1- copy a certain public key to the remote machine.
|
|
25
|
+
# scp ~/.ssh/id_rsa.pub $remote_user@$remote_host:~/.ssh/authorized_keys
|
|
26
|
+
# 2- Store the value on the remote in a file called .ssh/authorized_keys
|
|
27
|
+
# ssh $remote_user@$remote_host "echo $public_key >> ~/.ssh/authorized_keys"
|
|
28
|
+
# Idea from: https://www.chrisjhart.com/Windows-10-ssh-copy-id/
|
|
29
|
+
|
|
30
|
+
$key_value = cat ($env:USERPROFILE + "/.ssh/id_rsa.pub")
|
|
31
|
+
ssh $args[0] "powershell.exe -Command type $key_value >> .ssh/authorized_keys"
|
|
32
|
+
$my_keys='https://github.com/thisismygitrepo.keys'
|
|
33
|
+
(Invoke-WebRequest $my_keys).Content >> .ssh/authorized_keys
|
|
34
|
+
|
|
35
|
+
"""
|
|
2
36
|
|
|
3
37
|
# from platform import system
|
|
4
38
|
from machineconfig.utils.path_extended import PathExtended
|
machineconfig/scripts/python/{nw/devops_add_ssh_key.py → helpers_network/ssh_add_ssh_key.py}
RENAMED
|
@@ -13,9 +13,9 @@ import typer
|
|
|
13
13
|
console = Console()
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def get_add_ssh_key_script(path_to_key: PathExtended):
|
|
16
|
+
def get_add_ssh_key_script(path_to_key: PathExtended) -> str:
|
|
17
17
|
console.print(Panel("🔑 SSH KEY CONFIGURATION", title="[bold blue]SSH Setup[/bold blue]"))
|
|
18
|
-
if system() == "Linux":
|
|
18
|
+
if system() == "Linux" or system() == "Darwin":
|
|
19
19
|
authorized_keys = PathExtended.home().joinpath(".ssh/authorized_keys")
|
|
20
20
|
console.print(Panel(f"🐧 Linux SSH configuration\n📄 Authorized keys file: {authorized_keys}", title="[bold blue]System Info[/bold blue]"))
|
|
21
21
|
elif system() == "Windows":
|
|
@@ -35,10 +35,10 @@ def get_add_ssh_key_script(path_to_key: PathExtended):
|
|
|
35
35
|
program = ""
|
|
36
36
|
else:
|
|
37
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":
|
|
38
|
+
if system() == "Linux" or system() == "Darwin":
|
|
39
39
|
program = f"cat {path_to_key} >> ~/.ssh/authorized_keys"
|
|
40
40
|
elif system() == "Windows":
|
|
41
|
-
program_path = LIBRARY_ROOT.joinpath("setup_windows/add-sshkey.ps1")
|
|
41
|
+
program_path = LIBRARY_ROOT.joinpath("setup_windows/ssh/add-sshkey.ps1")
|
|
42
42
|
program = program_path.expanduser().read_text(encoding="utf-8")
|
|
43
43
|
place_holder = r'$sshfile = "$env:USERPROFILE\.ssh\pubkey.pub"'
|
|
44
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."
|
|
@@ -48,14 +48,14 @@ def get_add_ssh_key_script(path_to_key: PathExtended):
|
|
|
48
48
|
raise NotImplementedError
|
|
49
49
|
else:
|
|
50
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":
|
|
51
|
+
if system() == "Linux" or system() == "Darwin":
|
|
52
52
|
program = f"cat {path_to_key} > ~/.ssh/authorized_keys"
|
|
53
53
|
else:
|
|
54
|
-
program_path = LIBRARY_ROOT.joinpath("setup_windows/openssh-server_add-sshkey.ps1")
|
|
54
|
+
program_path = LIBRARY_ROOT.joinpath("setup_windows/ssh/openssh-server_add-sshkey.ps1")
|
|
55
55
|
program = PathExtended(program_path).expanduser().read_text(encoding="utf-8").replace('$sshfile=""', f'$sshfile="{path_to_key}"')
|
|
56
56
|
console.print(Panel("🔧 Configured PowerShell script for Windows\n📝 Set key path in script", title="[bold blue]Configuration[/bold blue]"))
|
|
57
57
|
|
|
58
|
-
if system() == "Linux":
|
|
58
|
+
if system() == "Linux" or system() == "Darwin":
|
|
59
59
|
program += """
|
|
60
60
|
sudo chmod 700 ~/.ssh
|
|
61
61
|
sudo chmod 644 ~/.ssh/authorized_keys
|
|
@@ -66,6 +66,16 @@ sudo service ssh --full-restart
|
|
|
66
66
|
return program
|
|
67
67
|
|
|
68
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
|
+
|
|
69
79
|
def main(pub_path: Annotated[Optional[str], typer.Argument(..., help="Path to the public key file")] = None,
|
|
70
80
|
pub_choose: Annotated[bool, typer.Option(..., "--choose", "-c", help="Choose from available public keys in ~/.ssh")] = False,
|
|
71
81
|
pub_val: Annotated[bool, typer.Option(..., "--paste", "-p", help="Paste the public key content manually")] = False,
|
|
@@ -127,6 +137,15 @@ def main(pub_path: Annotated[Optional[str], typer.Argument(..., help="Path to th
|
|
|
127
137
|
console.print(Panel("🚀 SSH KEY AUTHORIZATION READY\nRun the generated script to apply changes", box=box.DOUBLE_EDGE, title_align="left"))
|
|
128
138
|
from machineconfig.utils.code import run_shell_script
|
|
129
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"))
|
|
130
149
|
console.print(Panel("✅ SSH KEY AUTHORIZATION COMPLETED", box=box.DOUBLE_EDGE, title_align="left"))
|
|
131
150
|
|
|
132
151
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
3
|
from platform import system
|
|
4
|
-
from
|
|
4
|
+
from pathlib import Path
|
|
5
5
|
from rich.console import Console
|
|
6
6
|
from rich.panel import Panel
|
|
7
7
|
from rich import box
|
|
@@ -26,7 +26,7 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
|
|
|
26
26
|
results: dict[str, dict[str, str | bool]] = {}
|
|
27
27
|
issues_found: list[str] = []
|
|
28
28
|
|
|
29
|
-
ssh_dir =
|
|
29
|
+
ssh_dir = Path.home().joinpath(".ssh")
|
|
30
30
|
authorized_keys = ssh_dir.joinpath("authorized_keys")
|
|
31
31
|
|
|
32
32
|
console.print(Panel("🔐 Checking SSH directory and authorized_keys...", title="[bold blue]File Permissions[/bold blue]", border_style="blue"))
|
|
@@ -106,7 +106,7 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
|
|
|
106
106
|
|
|
107
107
|
console.print(Panel("🔌 Checking SSH port and listening status...", title="[bold blue]Network Status[/bold blue]", border_style="blue"))
|
|
108
108
|
|
|
109
|
-
sshd_config_paths = [
|
|
109
|
+
sshd_config_paths = [Path("/etc/ssh/sshd_config"), Path("/etc/sshd_config")]
|
|
110
110
|
sshd_config = None
|
|
111
111
|
for config_path in sshd_config_paths:
|
|
112
112
|
if config_path.exists():
|
|
@@ -236,7 +236,7 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
|
|
|
236
236
|
|
|
237
237
|
console.print(Panel("🗂️ Checking for problematic files in /etc/...", title="[bold blue]System Files[/bold blue]", border_style="blue"))
|
|
238
238
|
|
|
239
|
-
hosts_deny =
|
|
239
|
+
hosts_deny = Path("/etc/hosts.deny")
|
|
240
240
|
if hosts_deny.exists():
|
|
241
241
|
hosts_deny_content = hosts_deny.read_text(encoding="utf-8")
|
|
242
242
|
active_lines = [line.strip() for line in hosts_deny_content.splitlines() if line.strip() and not line.strip().startswith("#")]
|
|
@@ -252,14 +252,14 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
|
|
|
252
252
|
results["hosts_deny"] = {"status": "ok", "message": "/etc/hosts.deny does not exist", "action": ""}
|
|
253
253
|
console.print(Panel("✅ /etc/hosts.deny not present", title="[bold green]OK[/bold green]", border_style="green"))
|
|
254
254
|
|
|
255
|
-
hosts_allow =
|
|
255
|
+
hosts_allow = Path("/etc/hosts.allow")
|
|
256
256
|
if hosts_allow.exists():
|
|
257
257
|
results["hosts_allow"] = {"status": "ok", "message": "/etc/hosts.allow exists (check if needed)", "action": ""}
|
|
258
258
|
console.print(Panel("ℹ️ /etc/hosts.allow exists\n💡 Ensure it allows SSH if using TCP wrappers", title="[bold blue]Info[/bold blue]", border_style="blue"))
|
|
259
259
|
|
|
260
260
|
console.print(Panel("👤 Checking home directory permissions...", title="[bold blue]User Permissions[/bold blue]", border_style="blue"))
|
|
261
261
|
|
|
262
|
-
home_dir =
|
|
262
|
+
home_dir = Path.home()
|
|
263
263
|
home_stat = os.stat(home_dir)
|
|
264
264
|
home_perms = oct(home_stat.st_mode)[-3:]
|
|
265
265
|
|
|
@@ -294,7 +294,7 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
|
|
|
294
294
|
|
|
295
295
|
console.print(Panel("📋 Checking SSH logs for errors...", title="[bold blue]Logs[/bold blue]", border_style="blue"))
|
|
296
296
|
|
|
297
|
-
log_files = [
|
|
297
|
+
log_files = [Path("/var/log/auth.log"), Path("/var/log/secure")]
|
|
298
298
|
log_found = False
|
|
299
299
|
for log_file in log_files:
|
|
300
300
|
if log_file.exists():
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
3
|
from platform import system
|
|
4
|
-
from
|
|
4
|
+
from pathlib import Path
|
|
5
5
|
from rich.console import Console
|
|
6
6
|
from rich.panel import Panel
|
|
7
7
|
from rich import box
|
|
@@ -26,7 +26,7 @@ def ssh_debug_windows() -> dict[str, dict[str, str | bool]]:
|
|
|
26
26
|
results: dict[str, dict[str, str | bool]] = {}
|
|
27
27
|
issues_found: list[str] = []
|
|
28
28
|
|
|
29
|
-
ssh_dir =
|
|
29
|
+
ssh_dir = Path.home().joinpath(".ssh")
|
|
30
30
|
authorized_keys = ssh_dir.joinpath("authorized_keys")
|
|
31
31
|
|
|
32
32
|
console.print(Panel("🔐 Checking SSH directory and authorized_keys...", title="[bold blue]File Permissions[/bold blue]", border_style="blue"))
|
|
@@ -124,7 +124,7 @@ def ssh_debug_windows() -> dict[str, dict[str, str | bool]]:
|
|
|
124
124
|
|
|
125
125
|
console.print(Panel("🔌 Checking SSH port and listening status...", title="[bold blue]Network Status[/bold blue]", border_style="blue"))
|
|
126
126
|
|
|
127
|
-
sshd_config_paths = [
|
|
127
|
+
sshd_config_paths = [Path("C:\\ProgramData\\ssh\\sshd_config"), Path(os.environ.get("PROGRAMDATA", "C:\\ProgramData")).joinpath("ssh", "sshd_config")]
|
|
128
128
|
sshd_config = None
|
|
129
129
|
for config_path in sshd_config_paths:
|
|
130
130
|
if config_path.exists():
|
|
@@ -168,7 +168,7 @@ def ssh_debug_windows() -> dict[str, dict[str, str | bool]]:
|
|
|
168
168
|
if admin_authorized_keys_lines:
|
|
169
169
|
console.print(Panel("⚠️ IMPORTANT: Administrators group uses different authorized_keys location\n💡 For admin users, keys should be in: C:\\ProgramData\\ssh\\administrators_authorized_keys\n💡 Not in user's .ssh/authorized_keys!", title="[bold yellow]Admin Users[/bold yellow]", border_style="yellow"))
|
|
170
170
|
|
|
171
|
-
programdata_auth_keys =
|
|
171
|
+
programdata_auth_keys = Path(os.environ.get("PROGRAMDATA", "C:\\ProgramData")).joinpath("ssh", "administrators_authorized_keys")
|
|
172
172
|
if programdata_auth_keys.exists():
|
|
173
173
|
console.print(Panel("✅ administrators_authorized_keys file exists", title="[bold green]OK[/bold green]", border_style="green"))
|
|
174
174
|
else:
|
|
@@ -54,10 +54,16 @@ def main(
|
|
|
54
54
|
else:
|
|
55
55
|
cloud_resolved = cloud
|
|
56
56
|
repo_local_root = PathExtended.cwd() if repo is None else PathExtended(repo).expanduser().absolute()
|
|
57
|
-
|
|
57
|
+
try:
|
|
58
|
+
repo_local_obj = git.Repo(repo_local_root, search_parent_directories=True)
|
|
59
|
+
except git.InvalidGitRepositoryError:
|
|
60
|
+
typer.echo(f"[red]Error:[/] The specified path '{repo_local_root}' is not a valid git repository.")
|
|
61
|
+
typer.Exit(code=1)
|
|
62
|
+
return ""
|
|
58
63
|
repo_local_root = PathExtended(repo_local_obj.working_dir) # cwd might have been in a sub directory of repo_root, so its better to redefine it.
|
|
64
|
+
local_relative_home = PathExtended(repo_local_root.expanduser().absolute().relative_to(Path.home()))
|
|
59
65
|
PathExtended(CONFIG_ROOT).joinpath("remote").mkdir(parents=True, exist_ok=True)
|
|
60
|
-
repo_remote_root = PathExtended(CONFIG_ROOT).joinpath("remote",
|
|
66
|
+
repo_remote_root = PathExtended(CONFIG_ROOT).joinpath("remote", local_relative_home)
|
|
61
67
|
repo_remote_root.delete(sure=True)
|
|
62
68
|
try:
|
|
63
69
|
console.print(Panel("📥 DOWNLOADING REMOTE REPOSITORY", title_align="left", border_style="blue"))
|
|
@@ -99,7 +105,7 @@ git pull originEnc master
|
|
|
99
105
|
uv_project_dir = f"""{str(Path.home().joinpath("code/machineconfig"))}"""
|
|
100
106
|
uv_with = None
|
|
101
107
|
else:
|
|
102
|
-
uv_with = ["machineconfig>=
|
|
108
|
+
uv_with = ["machineconfig>=8.12"]
|
|
103
109
|
uv_project_dir = None
|
|
104
110
|
|
|
105
111
|
import tempfile
|
|
@@ -130,7 +136,8 @@ git pull originEnc master
|
|
|
130
136
|
def func2(remote_repo: str, local_repo: str, cloud: str):
|
|
131
137
|
from machineconfig.scripts.python.helpers_repos.sync import delete_remote_repo_copy_and_push_local
|
|
132
138
|
delete_remote_repo_copy_and_push_local(remote_repo=remote_repo, local_repo=local_repo, cloud=cloud)
|
|
133
|
-
program_1_py = lambda_to_python_script(lambda: func2(remote_repo=str(repo_remote_root), local_repo=str(repo_local_root), cloud=str(cloud_resolved)),
|
|
139
|
+
program_1_py = lambda_to_python_script(lambda: func2(remote_repo=str(repo_remote_root), local_repo=str(repo_local_root), cloud=str(cloud_resolved)),
|
|
140
|
+
in_global=True, import_module=False)
|
|
134
141
|
program1, _pyfile1 = get_uv_command_executing_python_script(python_script=program_1_py, uv_with=uv_with, uv_project_dir=uv_project_dir)
|
|
135
142
|
# ================================================================================
|
|
136
143
|
option2 = "Delete local repo and replace it with remote copy:"
|
|
@@ -155,7 +162,8 @@ sudo chmod +x $HOME/dotfiles/scripts/linux -R
|
|
|
155
162
|
inspect_repos(repo_local_root=repo_local_root, repo_remote_root=repo_remote_root)
|
|
156
163
|
# program_3_py = function_to_script(func=func, call_with_kwargs={"repo_local_root": str(repo_local_root), "repo_remote_root": str(repo_remote_root)})
|
|
157
164
|
# shell_file_3 = get_shell_file_executing_python_script(python_script=program_3_py, ve_path=None, executable=executable)
|
|
158
|
-
program_3_py = lambda_to_python_script(lambda: func(repo_local_root=str(repo_local_root), repo_remote_root=str(repo_remote_root)),
|
|
165
|
+
program_3_py = lambda_to_python_script(lambda: func(repo_local_root=str(repo_local_root), repo_remote_root=str(repo_remote_root)),
|
|
166
|
+
in_global=True, import_module=False)
|
|
159
167
|
program3, _pyfile3 = get_uv_command_executing_python_script(python_script=program_3_py, uv_with=uv_with, uv_project_dir=uv_project_dir)
|
|
160
168
|
# ================================================================================
|
|
161
169
|
|
|
@@ -38,7 +38,8 @@ def resolve_spec_path(directory: Optional[str], cloud: Optional[str]) -> Path:
|
|
|
38
38
|
repos_root = resolve_directory(directory)
|
|
39
39
|
from machineconfig.utils.path_extended import PathExtended
|
|
40
40
|
if not repos_root.exists() or repos_root.name != "repos.json":
|
|
41
|
-
|
|
41
|
+
relative_repos_root = PathExtended(repos_root).expanduser().absolute().relative_to(Path.home())
|
|
42
|
+
candidate = Path(CONFIG_ROOT).joinpath("repos").joinpath(relative_repos_root).joinpath("repos.json")
|
|
42
43
|
repos_root = candidate
|
|
43
44
|
if not repos_root.exists():
|
|
44
45
|
cloud_name: Optional[str]
|
|
@@ -242,7 +242,8 @@ def main_record(repos_root: Path):
|
|
|
242
242
|
tree_structure = build_tree_structure(repo_records, repos_root)
|
|
243
243
|
print(tree_structure)
|
|
244
244
|
|
|
245
|
-
|
|
245
|
+
relative_repos_root = PathExtended(repos_root).expanduser().absolute().relative_to(Path.home())
|
|
246
|
+
save_path = CONFIG_ROOT.joinpath("repos").joinpath(relative_repos_root).joinpath("repos.json")
|
|
246
247
|
save_json(obj=res, path=save_path, indent=4)
|
|
247
248
|
pprint(f"📁 Result saved at {PathExtended(save_path)}")
|
|
248
249
|
print(">>>>>>>>> Finished Recording")
|