atomicshop 3.3.28__py3-none-any.whl → 3.10.0__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 atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/install_ca_certificate.py +172 -0
- atomicshop/a_mains/process_from_port.py +119 -0
- atomicshop/a_mains/set_default_dns_gateway.py +90 -0
- atomicshop/basics/strings.py +1 -1
- atomicshop/certificates.py +2 -2
- atomicshop/dns.py +26 -28
- atomicshop/etws/traces/trace_tcp.py +1 -2
- atomicshop/mitm/centered_settings.py +133 -0
- atomicshop/mitm/config_static.py +18 -43
- atomicshop/mitm/connection_thread_worker.py +376 -162
- atomicshop/mitm/engines/__parent/recorder___parent.py +1 -1
- atomicshop/mitm/engines/__parent/requester___parent.py +1 -1
- atomicshop/mitm/engines/__parent/responder___parent.py +15 -2
- atomicshop/mitm/engines/create_module_template.py +1 -2
- atomicshop/mitm/import_config.py +79 -88
- atomicshop/mitm/initialize_engines.py +1 -2
- atomicshop/mitm/message.py +5 -4
- atomicshop/mitm/mitm_main.py +222 -121
- atomicshop/mitm/recs_files.py +61 -5
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/networks.py +108 -93
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/ubuntu_permissions.py +47 -0
- atomicshop/print_api.py +3 -5
- atomicshop/python_functions.py +23 -108
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +115 -51
- atomicshop/web.py +20 -7
- atomicshop/web_apis/google_llm.py +22 -14
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +2 -1
- atomicshop/wrappers/dockerw/dockerw.py +2 -2
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +5 -5
- atomicshop/wrappers/githubw.py +175 -63
- atomicshop/wrappers/loggingw/handlers.py +1 -1
- atomicshop/wrappers/loggingw/loggingw.py +17 -1
- atomicshop/wrappers/netshw.py +124 -3
- atomicshop/wrappers/playwrightw/scenarios.py +1 -1
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/psutil_networks.py +9 -0
- atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +3 -105
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +3 -57
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +12 -27
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +15 -9
- atomicshop/wrappers/socketw/certificator.py +19 -9
- atomicshop/wrappers/socketw/creator.py +30 -7
- atomicshop/wrappers/socketw/dns_server.py +6 -6
- atomicshop/wrappers/socketw/exception_wrapper.py +3 -3
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +29 -9
- atomicshop/wrappers/socketw/sender.py +10 -9
- atomicshop/wrappers/socketw/sni.py +23 -6
- atomicshop/wrappers/socketw/{base.py → socket_base.py} +33 -1
- atomicshop/wrappers/socketw/socket_client.py +6 -8
- atomicshop/wrappers/socketw/socket_wrapper.py +82 -21
- atomicshop/wrappers/socketw/ssl_base.py +6 -2
- atomicshop/wrappers/win_auditw.py +189 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/METADATA +25 -30
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/RECORD +74 -88
- atomicshop/_basics_temp.py +0 -101
- atomicshop/a_installs/ubuntu/docker_rootless.py +0 -11
- atomicshop/a_installs/ubuntu/docker_sudo.py +0 -11
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
- atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
- atomicshop/addons/package_setup/Setup.cmd +0 -7
- atomicshop/archiver/__init__.py +0 -0
- atomicshop/archiver/_search_in_zip.py +0 -189
- atomicshop/archiver/search_in_archive.py +0 -284
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -73
- atomicshop/archiver/shutils.py +0 -34
- atomicshop/archiver/zips.py +0 -353
- atomicshop/file_types.py +0 -24
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/script_as_string_processor.py +0 -42
- atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
- atomicshop/ssh_scripts/process_from_port.py +0 -27
- atomicshop/wrappers/_process_wrapper_curl.py +0 -27
- atomicshop/wrappers/_process_wrapper_tar.py +0 -21
- atomicshop/wrappers/dockerw/install_docker.py +0 -449
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/get_process.py +0 -123
- /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compile.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.dll +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.exp +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.lib +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +0 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/WHEEL +0 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/licenses/LICENSE.txt +0 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/top_level.txt +0 -0
|
@@ -1,449 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import os
|
|
3
|
-
import subprocess
|
|
4
|
-
import getpass
|
|
5
|
-
import tempfile
|
|
6
|
-
import textwrap
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
|
|
9
|
-
from ... import process, filesystem
|
|
10
|
-
from ...permissions import permissions, ubuntu_permissions
|
|
11
|
-
from ...print_api import print_api
|
|
12
|
-
from .. import ubuntu_terminal
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
PREPARATION_OUTPUT_DIR: str = str(Path(__file__).parent / "offline-bundle")
|
|
16
|
-
PREPARATION_OUTPUT_ZIP: str = f"{PREPARATION_OUTPUT_DIR}.zip"
|
|
17
|
-
GET_DOCKER_URL: str = "https://get.docker.com"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def is_docker_installed():
|
|
21
|
-
"""
|
|
22
|
-
The function will check if docker is installed.
|
|
23
|
-
:return: bool.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
try:
|
|
27
|
-
# Run the command 'docker --version'
|
|
28
|
-
result = subprocess.run(['docker', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
29
|
-
|
|
30
|
-
# Check if the command was successful
|
|
31
|
-
if result.returncode == 0:
|
|
32
|
-
message = f"Docker is installed. Version: {result.stdout.strip()}"
|
|
33
|
-
print_api(message, color='green')
|
|
34
|
-
return True
|
|
35
|
-
else:
|
|
36
|
-
print_api("Docker is not installed.")
|
|
37
|
-
return False
|
|
38
|
-
except FileNotFoundError:
|
|
39
|
-
print_api("Docker command not found. Docker is not installed.")
|
|
40
|
-
return False
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def add_current_user_to_docker_group(print_kwargs: dict = None):
|
|
44
|
-
"""
|
|
45
|
-
The function will add the current user to the docker group.
|
|
46
|
-
|
|
47
|
-
:param print_kwargs: dict, the print arguments.
|
|
48
|
-
:return:
|
|
49
|
-
"""
|
|
50
|
-
# Check if current user that executed the script is a sudo user. If not, use the current user.
|
|
51
|
-
sudo_executer_username: str = ubuntu_permissions.get_sudo_executer_username()
|
|
52
|
-
if sudo_executer_username:
|
|
53
|
-
current_user = sudo_executer_username
|
|
54
|
-
else:
|
|
55
|
-
current_user = getpass.getuser()
|
|
56
|
-
|
|
57
|
-
# Add the current user to the docker group.
|
|
58
|
-
# subprocess.check_call(['sudo', 'usermod', '-aG', 'docker', current_user])
|
|
59
|
-
command = f"sudo usermod -aG docker {current_user}"
|
|
60
|
-
# Execute the command
|
|
61
|
-
subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
62
|
-
|
|
63
|
-
# Check if the user was added to the docker group.
|
|
64
|
-
result = subprocess.run(['groups', current_user], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
65
|
-
if 'docker' in result.stdout:
|
|
66
|
-
print_api(f"User {current_user} was added to the docker group.", color='green', **(print_kwargs or {}))
|
|
67
|
-
return True
|
|
68
|
-
else:
|
|
69
|
-
print_api(f"User {current_user} was not added to the docker group. Try executing with sudo", color='red',
|
|
70
|
-
**(print_kwargs or {}))
|
|
71
|
-
return False
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def install_docker_ubuntu(
|
|
75
|
-
use_docker_installer: bool = True,
|
|
76
|
-
rootless: bool = False,
|
|
77
|
-
add_current_user_to_docker_group_bool: bool = False
|
|
78
|
-
) -> int:
|
|
79
|
-
"""
|
|
80
|
-
The function will install docker on ubuntu.
|
|
81
|
-
Note: If you want to install docker in rootless mode, you need to run the script without sudo.
|
|
82
|
-
|
|
83
|
-
:param rootless: bool, if True, the rootless installation will be performed.
|
|
84
|
-
Meaning, you will be able to run the 'docker' command without sudo and you will not need to add the
|
|
85
|
-
current user to the docker group.
|
|
86
|
-
:param use_docker_installer: bool, if True, the docker installer will be used.
|
|
87
|
-
If False, the docker will be installed using the apt package manager, custom repo and keyring.
|
|
88
|
-
:param add_current_user_to_docker_group_bool: bool, if True, the current user will be added to the docker group.
|
|
89
|
-
So the user will be able to run the 'docker' command without sudo. If you install docker in rootless mode
|
|
90
|
-
this is not needed.
|
|
91
|
-
|
|
92
|
-
Usage in main.py (run with sudo):
|
|
93
|
-
import sys
|
|
94
|
-
from atomicshop.wrappers.dockerw import install_docker
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def main():
|
|
98
|
-
execution_result: int = install_docker.install_docker_ubuntu()
|
|
99
|
-
return execution_result
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if __name__ == '__main__':
|
|
103
|
-
sys.exit(main())
|
|
104
|
-
"""
|
|
105
|
-
|
|
106
|
-
if rootless and permissions.is_admin():
|
|
107
|
-
print_api('Rootless installation requires running the script without sudo.', color='red')
|
|
108
|
-
sys.exit()
|
|
109
|
-
|
|
110
|
-
if use_docker_installer:
|
|
111
|
-
if not ubuntu_terminal.is_executable_exists('curl'):
|
|
112
|
-
print_api('curl is not installed, installing...', color='yellow')
|
|
113
|
-
ubuntu_terminal.update_system_packages()
|
|
114
|
-
ubuntu_terminal.install_packages(['curl'])
|
|
115
|
-
|
|
116
|
-
# Use the docker installer script.
|
|
117
|
-
# The script will install docker and add the current user to the docker group.
|
|
118
|
-
# The script will also install docker-compose and docker-buildx.
|
|
119
|
-
# process.execute_script('curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh', shell=True)
|
|
120
|
-
process.execute_script('curl -fsSL https://get.docker.com | sh', shell=True)
|
|
121
|
-
# subprocess.run("curl -fsSL https://get.docker.com | sh", shell=True, check=True)
|
|
122
|
-
# process.execute_script('curl -fsSL https://get.docker.com -o get-docker.sh', shell=True)
|
|
123
|
-
# process.execute_script('sh get-docker.sh', shell=True)
|
|
124
|
-
# filesystem.remove_file('get-docker.sh')
|
|
125
|
-
else:
|
|
126
|
-
# Remove the existing keyrings, so we will not be asked to overwrite it if it exists.
|
|
127
|
-
docker_keyring_file_path: str = "/etc/apt/keyrings/docker.gpg"
|
|
128
|
-
filesystem.remove_file(docker_keyring_file_path)
|
|
129
|
-
|
|
130
|
-
script = f"""
|
|
131
|
-
# Step 1: Set up Docker's apt repository
|
|
132
|
-
sudo apt-get update
|
|
133
|
-
sudo apt-get install -y ca-certificates curl gnupg
|
|
134
|
-
sudo install -m 0755 -d /etc/apt/keyrings
|
|
135
|
-
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
|
136
|
-
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
|
137
|
-
|
|
138
|
-
# Add the repository to Apt sources
|
|
139
|
-
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
140
|
-
sudo apt-get update
|
|
141
|
-
|
|
142
|
-
# Step 2: Install the Docker packages
|
|
143
|
-
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
|
|
144
|
-
|
|
145
|
-
# Step 3: Verify the installation
|
|
146
|
-
# sudo docker run hello-world
|
|
147
|
-
|
|
148
|
-
# Add Privileges to run docker without sudo. Add current user to Docker superuser group.
|
|
149
|
-
# sudo usermod -aG docker $USER
|
|
150
|
-
"""
|
|
151
|
-
|
|
152
|
-
process.execute_script(script, shell=True)
|
|
153
|
-
|
|
154
|
-
if rootless:
|
|
155
|
-
# Install uidmap package.
|
|
156
|
-
if not ubuntu_terminal.is_package_installed('uidmap'):
|
|
157
|
-
print_api('uidmap is not installed, installing...', color='yellow')
|
|
158
|
-
ubuntu_terminal.update_system_packages()
|
|
159
|
-
ubuntu_terminal.install_packages(['uidmap'])
|
|
160
|
-
|
|
161
|
-
with ubuntu_permissions.temporary_regular_permissions():
|
|
162
|
-
# After 'get-docker.sh' execution, we will install docker in rootless mode.
|
|
163
|
-
# process.execute_script('dockerd-rootless-setuptool.sh install', shell=True, as_regular_user=True)
|
|
164
|
-
process.execute_script(
|
|
165
|
-
'/usr/bin/dockerd-rootless-setuptool.sh install',
|
|
166
|
-
as_regular_user=True,
|
|
167
|
-
shell=True,
|
|
168
|
-
executable=None)
|
|
169
|
-
|
|
170
|
-
# Start and enable the docker service in user mode.
|
|
171
|
-
docker_start_command = ubuntu_terminal.get_command_execution_as_sudo_executer(
|
|
172
|
-
'systemctl --user start docker.service')
|
|
173
|
-
docker_enable_command = ubuntu_terminal.get_command_execution_as_sudo_executer(
|
|
174
|
-
'systemctl --user enable docker.service')
|
|
175
|
-
print_api('Starting and enabling the docker service in user mode...')
|
|
176
|
-
process.execute_script(docker_start_command, shell=True, executable=None)
|
|
177
|
-
process.execute_script(docker_enable_command, shell=True, executable=None)
|
|
178
|
-
|
|
179
|
-
print_api('Executing "loginctl enable-linger" to enable Docker to run when the user is not logged in...')
|
|
180
|
-
non_sudo_executer = ubuntu_permissions.get_sudo_executer_username()
|
|
181
|
-
# Enable lingering so Docker runs when the user is not logged in
|
|
182
|
-
process.execute_script(f'sudo loginctl enable-linger {non_sudo_executer}', shell=True)
|
|
183
|
-
|
|
184
|
-
print_api('Adding $HOME/bin to your PATH...')
|
|
185
|
-
# Add $HOME/bin to your PATH if it's not already there.
|
|
186
|
-
with ubuntu_permissions.temporary_regular_permissions():
|
|
187
|
-
ubuntu_terminal.add_path_to_bashrc(as_regular_user=True)
|
|
188
|
-
|
|
189
|
-
# Add appropriate permissions to the docker socket, so the user can run docker commands without sudo in python.
|
|
190
|
-
# with open('/etc/profile.d/docker_vars.sh', 'w') as file:
|
|
191
|
-
# file.write('export DOCKER_HOST=unix:///run/user/1000/docker.sock')
|
|
192
|
-
|
|
193
|
-
# Since we are installing the rootless mode, this script runs without sudo, so to add the DOCKER_HOST variable
|
|
194
|
-
# to the environment, we need to add it to the /etc/profile.d/docker_vars.sh file with sudo.
|
|
195
|
-
command = "echo 'export DOCKER_HOST=unix:///run/user/1000/docker.sock' | sudo tee /etc/profile.d/docker_vars.sh"
|
|
196
|
-
subprocess.run(command, shell=True, check=True)
|
|
197
|
-
|
|
198
|
-
# ubuntu_terminal.add_line_to_bashrc(
|
|
199
|
-
# 'export DOCKER_HOST=unix:///run/user/1000/docker.sock', as_regular_user=True)
|
|
200
|
-
# process.execute_script('export DOCKER_HOST=unix:///run/user/1000/docker.sock', shell=True)
|
|
201
|
-
# Restart shell.
|
|
202
|
-
# process.execute_script('source ~/.bashrc', shell=True)
|
|
203
|
-
|
|
204
|
-
if add_current_user_to_docker_group_bool:
|
|
205
|
-
# Check if current user that executed the script is a sudo user. If not, use the current user.
|
|
206
|
-
# Add the current user to the docker group.
|
|
207
|
-
add_current_user_to_docker_group()
|
|
208
|
-
|
|
209
|
-
# Verify the installation.
|
|
210
|
-
result: list = process.execute_with_live_output('sudo docker run hello-world')
|
|
211
|
-
else:
|
|
212
|
-
result: list = process.execute_with_live_output('docker run hello-world')
|
|
213
|
-
|
|
214
|
-
print_api('\n'.join(result))
|
|
215
|
-
|
|
216
|
-
if 'Hello from Docker!' in '\n'.join(result):
|
|
217
|
-
print_api('Docker installed successfully.', color='green')
|
|
218
|
-
return 0
|
|
219
|
-
else:
|
|
220
|
-
print_api('Docker installation failed.', color='red')
|
|
221
|
-
print_api('Please check the logs above for more information.', color='red')
|
|
222
|
-
return 1
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
def prepare_offline_installation_bundle():
|
|
226
|
-
# The Bash script in a single triple-quoted string - this is to easier copy-paste it if needed to run directly.
|
|
227
|
-
bash_script = textwrap.dedent(r"""#!/usr/bin/env bash
|
|
228
|
-
#
|
|
229
|
-
# Build an offline-install bundle for Docker Engine on Ubuntu 24.04 LTS.
|
|
230
|
-
# The package list is auto-discovered from `get.docker.com --dry-run`.
|
|
231
|
-
#
|
|
232
|
-
# sudo ./prepare_docker_offline.sh [/path/to/output_dir]
|
|
233
|
-
#
|
|
234
|
-
set -Eeuo pipefail
|
|
235
|
-
|
|
236
|
-
################################################################################
|
|
237
|
-
# CLI PARAMETERS
|
|
238
|
-
# $1 → OUTDIR (already supported: where to build the bundle)
|
|
239
|
-
# $2 → GET_DOCKER_URL (defaults to https://get.docker.com)
|
|
240
|
-
# $3 → OUTPUT_ZIP (defaults to "$OUTDIR.zip")
|
|
241
|
-
################################################################################
|
|
242
|
-
OUTDIR="${1:-"$PWD/offline-bundle"}"
|
|
243
|
-
GET_DOCKER_URL="${2:-https://get.docker.com}"
|
|
244
|
-
OUTPUT_ZIP="${3:-$OUTDIR.zip}"
|
|
245
|
-
|
|
246
|
-
die() { echo "ERROR: $*" >&2; exit 1; }
|
|
247
|
-
need_root() { [[ $EUID -eq 0 ]] || die "Run as root (use sudo)"; }
|
|
248
|
-
need_cmd() {
|
|
249
|
-
local cmd=$1
|
|
250
|
-
local pkg=${2:-$1} # default package == command
|
|
251
|
-
if ! command -v "$cmd" &>/dev/null; then
|
|
252
|
-
echo "[*] $cmd not found – installing $pkg ..."
|
|
253
|
-
apt-get update -qq
|
|
254
|
-
DEBIAN_FRONTEND=noninteractive \
|
|
255
|
-
apt-get install -y --no-install-recommends "$pkg" || \
|
|
256
|
-
die "Unable to install required package: $pkg"
|
|
257
|
-
fi
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
need_root
|
|
261
|
-
need_cmd curl
|
|
262
|
-
|
|
263
|
-
echo "[*] Discovering package list via get.docker.com --dry-run ..."
|
|
264
|
-
DRY_LOG=$(curl -fsSL "$GET_DOCKER_URL" | bash -s -- --dry-run)
|
|
265
|
-
|
|
266
|
-
echo "[*] Determining package list via --dry-run ..."
|
|
267
|
-
PKGS=$(printf '%s\n' "$DRY_LOG" | sed -n 's/.* install \(.*\) >\/dev\/null.*/\1/p')
|
|
268
|
-
|
|
269
|
-
if ! grep -q '\S' <<< "$PKGS"; then
|
|
270
|
-
echo "No packages detected in dry-run output – aborting." >&2
|
|
271
|
-
exit 1
|
|
272
|
-
fi
|
|
273
|
-
|
|
274
|
-
echo "[*] Install Docker before preparing the offline bundle."
|
|
275
|
-
curl -fsSL "$GET_DOCKER_URL" | sh
|
|
276
|
-
|
|
277
|
-
mkdir -p "$OUTDIR"/packages
|
|
278
|
-
echo "[*] Output directory: $OUTDIR"
|
|
279
|
-
|
|
280
|
-
echo "Packages to install:"
|
|
281
|
-
echo "$PKGS"
|
|
282
|
-
|
|
283
|
-
echo "[*] Downloading packages and all dependencies …"
|
|
284
|
-
apt-get update -qq
|
|
285
|
-
apt-get clean
|
|
286
|
-
mkdir -p /var/cache/apt/archives/partial
|
|
287
|
-
apt-get -y --download-only --reinstall install $PKGS
|
|
288
|
-
cp -v /var/cache/apt/archives/*.deb "$OUTDIR/packages/"
|
|
289
|
-
echo "[*] $(ls "$OUTDIR/packages" | wc -l) .deb files written to packages/"
|
|
290
|
-
|
|
291
|
-
echo "[*] Building local Packages.gz index …"
|
|
292
|
-
pushd "$OUTDIR/packages" >/dev/null
|
|
293
|
-
for deb in *.deb; do
|
|
294
|
-
dpkg-deb -f "$deb" Package
|
|
295
|
-
done | awk '{printf "%s\tmisc\toptional\n",$1}' > override
|
|
296
|
-
apt-ftparchive packages . override | tee Packages | gzip -9c > Packages.gz
|
|
297
|
-
popd >/dev/null
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
echo ">> Checking for Docker ..."
|
|
301
|
-
command -v docker >/dev/null 2>&1 || { echo "Docker not found."; exit 1; }
|
|
302
|
-
|
|
303
|
-
# Pack final bundle
|
|
304
|
-
echo "[*] Creating a zip archive ..."
|
|
305
|
-
parent_dir=$(dirname "$OUTDIR")
|
|
306
|
-
base_name=$(basename "$OUTDIR")
|
|
307
|
-
|
|
308
|
-
# Create new shell, cd into the directory, and zip the contents. So that the zip file will not contain the full path.
|
|
309
|
-
(
|
|
310
|
-
cd "$parent_dir"
|
|
311
|
-
zip -rq "$OUTPUT_ZIP" "$base_name"
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
rm -rf "$OUTDIR"
|
|
315
|
-
echo "Docker offline bundle created at $OUTPUT_ZIP"
|
|
316
|
-
echo
|
|
317
|
-
echo "Copy the zip file and the offline installation python script to the target machine and execute."
|
|
318
|
-
""")
|
|
319
|
-
|
|
320
|
-
# Write it to a secure temporary file.
|
|
321
|
-
with tempfile.NamedTemporaryFile('w', delete=False, suffix='.sh') as f:
|
|
322
|
-
f.write(bash_script)
|
|
323
|
-
temp_path = f.name
|
|
324
|
-
os.chmod(temp_path, 0o755) # make it executable
|
|
325
|
-
|
|
326
|
-
cmd = [
|
|
327
|
-
"sudo", "bash", temp_path,
|
|
328
|
-
PREPARATION_OUTPUT_DIR,
|
|
329
|
-
GET_DOCKER_URL,
|
|
330
|
-
PREPARATION_OUTPUT_ZIP,
|
|
331
|
-
]
|
|
332
|
-
|
|
333
|
-
# Run it and stream output live.
|
|
334
|
-
try:
|
|
335
|
-
subprocess.run(cmd, check=True)
|
|
336
|
-
finally:
|
|
337
|
-
# 5. Clean up the temp file unless you want to inspect it.
|
|
338
|
-
os.remove(temp_path)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
def install_offline_installation_bundle():
|
|
342
|
-
bash_script = textwrap.dedent(r"""#!/usr/bin/env bash
|
|
343
|
-
# Offline installer for the Docker bundle produced by prepare_docker_offline.sh
|
|
344
|
-
set -euo pipefail
|
|
345
|
-
|
|
346
|
-
die() { echo "ERROR: $*" >&2; exit 1; }
|
|
347
|
-
need_root() { [[ $EUID -eq 0 ]] || die "Run as root (use sudo)"; }
|
|
348
|
-
|
|
349
|
-
need_root
|
|
350
|
-
|
|
351
|
-
# ------------------------------------------------------------------------------
|
|
352
|
-
# Paths
|
|
353
|
-
# ------------------------------------------------------------------------------
|
|
354
|
-
BUNDLE_ZIP="${1:-"$PWD/offline-bundle.zip"}"
|
|
355
|
-
|
|
356
|
-
BUNDLE_DIR="${BUNDLE_ZIP%.zip}" # remove .zip suffix
|
|
357
|
-
REPO_DIR="$BUNDLE_DIR/packages" # contains *.deb + Packages
|
|
358
|
-
OFFLINE_LIST="/etc/apt/sources.list.d/docker-offline.list"
|
|
359
|
-
|
|
360
|
-
# Extract zip archive if it exists
|
|
361
|
-
if [[ -f "$BUNDLE_ZIP" ]]; then
|
|
362
|
-
echo "[*] Extracting offline bundle from $BUNDLE_ZIP ..."
|
|
363
|
-
mkdir -p "$BUNDLE_DIR"
|
|
364
|
-
unzip -q "$BUNDLE_ZIP" -d "."
|
|
365
|
-
else
|
|
366
|
-
die "Bundle zip file '$BUNDLE_ZIP' not found. Provide a valid path."
|
|
367
|
-
fi
|
|
368
|
-
|
|
369
|
-
TEMP_PARTS="$(mktemp -d)" # empty dir ⇒ no extra lists
|
|
370
|
-
|
|
371
|
-
# ------------------------------------------------------------------------------
|
|
372
|
-
# Helper to clean up even if the script aborts
|
|
373
|
-
# ------------------------------------------------------------------------------
|
|
374
|
-
cleanup() {
|
|
375
|
-
sudo rm -f "$OFFLINE_LIST"
|
|
376
|
-
sudo rm -rf "$TEMP_PARTS"
|
|
377
|
-
}
|
|
378
|
-
trap cleanup EXIT
|
|
379
|
-
|
|
380
|
-
# ------------------------------------------------------------------------------
|
|
381
|
-
# 1. Add the local repository (trusted) as the *only* source we will use
|
|
382
|
-
# ------------------------------------------------------------------------------
|
|
383
|
-
echo "[*] Adding temporary APT source for the offline bundle …"
|
|
384
|
-
echo "deb [trusted=yes] file:$REPO_DIR ./" | sudo tee "$OFFLINE_LIST" >/dev/null
|
|
385
|
-
|
|
386
|
-
# Ensure plain index exists (APT always understands the un-compressed form)
|
|
387
|
-
if [[ ! -f "$REPO_DIR/Packages" && -f "$REPO_DIR/Packages.gz" ]]; then
|
|
388
|
-
gunzip -c "$REPO_DIR/Packages.gz" > "$REPO_DIR/Packages"
|
|
389
|
-
fi
|
|
390
|
-
|
|
391
|
-
# ------------------------------------------------------------------------------
|
|
392
|
-
# 2. Update metadata – but ONLY from our offline list
|
|
393
|
-
# ------------------------------------------------------------------------------
|
|
394
|
-
echo "[*] Updating APT metadata – offline only …"
|
|
395
|
-
sudo apt-get -o Dir::Etc::sourcelist="$OFFLINE_LIST" \
|
|
396
|
-
-o Dir::Etc::sourceparts="$TEMP_PARTS" \
|
|
397
|
-
-o APT::Get::List-Cleanup="0" \
|
|
398
|
-
update -qq
|
|
399
|
-
|
|
400
|
-
# ------------------------------------------------------------------------------
|
|
401
|
-
# 3. Figure out which packages are inside the bundle
|
|
402
|
-
# ------------------------------------------------------------------------------
|
|
403
|
-
PKGS=$(awk '/^Package: /{print $2}' "$REPO_DIR/Packages")
|
|
404
|
-
|
|
405
|
-
echo "[*] Installing:"
|
|
406
|
-
printf ' • %s\n' $PKGS
|
|
407
|
-
|
|
408
|
-
# ------------------------------------------------------------------------------
|
|
409
|
-
# 4. Install them, again restricting APT to the offline repo only
|
|
410
|
-
# ------------------------------------------------------------------------------
|
|
411
|
-
sudo apt-get -y \
|
|
412
|
-
-o Dir::Etc::sourcelist="$OFFLINE_LIST" \
|
|
413
|
-
-o Dir::Etc::sourceparts="$TEMP_PARTS" \
|
|
414
|
-
install $PKGS
|
|
415
|
-
|
|
416
|
-
echo "[✓] Docker installed completely offline!"
|
|
417
|
-
|
|
418
|
-
usage() {
|
|
419
|
-
echo "Usage: $0 <image-archive.tar.gz>"
|
|
420
|
-
exit 1
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
echo ">> Checking for Docker ..."
|
|
424
|
-
command -v docker >/dev/null 2>&1 || {
|
|
425
|
-
echo "Docker is not installed; install Docker and try again."
|
|
426
|
-
exit 1
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
echo "Removing extracted files..."
|
|
430
|
-
rm -rf "$BUNDLE_DIR"
|
|
431
|
-
""")
|
|
432
|
-
|
|
433
|
-
# Write it to a secure temporary file.
|
|
434
|
-
with tempfile.NamedTemporaryFile('w', delete=False, suffix='.sh') as f:
|
|
435
|
-
f.write(bash_script)
|
|
436
|
-
temp_path = f.name
|
|
437
|
-
os.chmod(temp_path, 0o755) # make it executable
|
|
438
|
-
|
|
439
|
-
cmd = [
|
|
440
|
-
"sudo", "bash", temp_path,
|
|
441
|
-
PREPARATION_OUTPUT_ZIP, # $1 BUNDLE_ZIP
|
|
442
|
-
]
|
|
443
|
-
|
|
444
|
-
# 4. Run it and stream output live.
|
|
445
|
-
try:
|
|
446
|
-
subprocess.run(cmd, check=True)
|
|
447
|
-
finally:
|
|
448
|
-
# 5. Clean up the temp file unless you want to inspect it.
|
|
449
|
-
os.remove(temp_path)
|
atomicshop/wrappers/ffmpegw.py
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import fnmatch
|
|
2
|
-
import os
|
|
3
|
-
import shlex
|
|
4
|
-
|
|
5
|
-
from ..print_api import print_api
|
|
6
|
-
from ..tempfiles import TempFile
|
|
7
|
-
from .githubw import GitHubWrapper
|
|
8
|
-
from ..process import execute_with_live_output
|
|
9
|
-
from ..filesystem import create_directory
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class FFmpegWrapper:
|
|
13
|
-
def __init__(self, working_directory: str = str(), ffmpeg_exe_path: str = str()):
|
|
14
|
-
self.working_directory: str = working_directory
|
|
15
|
-
self.ffmpeg_exe_path: str = ffmpeg_exe_path
|
|
16
|
-
self.relative_path: str = 'bin'
|
|
17
|
-
self.ffmpeg_exe_name: str = 'ffmpeg.exe'
|
|
18
|
-
|
|
19
|
-
# Variables to download the latest release from GitHub in case execution fails.
|
|
20
|
-
self.git_user: str = 'GyanD'
|
|
21
|
-
self.git_repo: str = 'codexffmpeg'
|
|
22
|
-
self.git_latest_release_pattern: str = '*full_build.zip'
|
|
23
|
-
|
|
24
|
-
# ffmpeg Release directory name.
|
|
25
|
-
self.ffmpeg_release_directory_name: str = \
|
|
26
|
-
f"ffmpeg_{self.git_latest_release_pattern.replace('*', '').split('.')[0]}"
|
|
27
|
-
self.ffmpeg_release_directory_path: str = str()
|
|
28
|
-
|
|
29
|
-
# Execute functions.
|
|
30
|
-
self.build_ffmpeg_exe_and_directory_path()
|
|
31
|
-
|
|
32
|
-
def build_ffmpeg_exe_and_directory_path(self):
|
|
33
|
-
# If working directory was specified, but not the full path to exe.
|
|
34
|
-
if self.working_directory and not self.ffmpeg_exe_path:
|
|
35
|
-
self.ffmpeg_release_directory_path = self.working_directory + os.sep + self.ffmpeg_release_directory_name
|
|
36
|
-
self.ffmpeg_exe_path = \
|
|
37
|
-
self.ffmpeg_release_directory_path + os.sep + self.relative_path + os.sep + self.ffmpeg_exe_name
|
|
38
|
-
# If no working directory and no path to exe was specified.
|
|
39
|
-
elif not self.working_directory and not self.ffmpeg_exe_path:
|
|
40
|
-
# Use just 'ffmpeg.exe' as path to exe. Maybe it is already installed and is in environment PATH var.
|
|
41
|
-
self.ffmpeg_exe_path = self.ffmpeg_exe_name
|
|
42
|
-
|
|
43
|
-
def change_to_temp_directory(self):
|
|
44
|
-
temp_file = TempFile()
|
|
45
|
-
self.working_directory = temp_file.directory
|
|
46
|
-
self.ffmpeg_exe_path = str()
|
|
47
|
-
self.build_ffmpeg_exe_and_directory_path()
|
|
48
|
-
|
|
49
|
-
def download_ffmpeg_and_extract(self):
|
|
50
|
-
github_wrapper = GitHubWrapper(user_name=self.git_user, repo_name=self.git_repo)
|
|
51
|
-
github_wrapper.build_links_from_user_and_repo()
|
|
52
|
-
github_wrapper.download_and_extract_latest_release(
|
|
53
|
-
target_directory=self.ffmpeg_release_directory_path, string_pattern=self.git_latest_release_pattern,
|
|
54
|
-
archive_remove_first_directory=True)
|
|
55
|
-
|
|
56
|
-
def execute_ffmpeg(self, cmd_list: list):
|
|
57
|
-
continue_loop: bool = True
|
|
58
|
-
while continue_loop:
|
|
59
|
-
# If first entry contains 'ffmpeg.exe' and it is not 'self.ffmpeg_exe_path' already.
|
|
60
|
-
if self.ffmpeg_exe_name in cmd_list[0] and cmd_list[0] != self.ffmpeg_exe_path:
|
|
61
|
-
# We'll change it to the updated one.
|
|
62
|
-
cmd_list[0] = self.ffmpeg_exe_path
|
|
63
|
-
# If first entry doesn't contain 'ffmpeg.exe'.
|
|
64
|
-
elif self.ffmpeg_exe_name not in cmd_list[0]:
|
|
65
|
-
# We'll insert the current path into first entry.
|
|
66
|
-
cmd_list.insert(0, self.ffmpeg_exe_path)
|
|
67
|
-
|
|
68
|
-
output_strings: list = [
|
|
69
|
-
'Input',
|
|
70
|
-
'Output',
|
|
71
|
-
'video:'
|
|
72
|
-
]
|
|
73
|
-
|
|
74
|
-
try:
|
|
75
|
-
print(f'FFmpeg processing: {shlex.join(cmd_list)}')
|
|
76
|
-
result_lines = execute_with_live_output(
|
|
77
|
-
cmd=cmd_list, output_strings=output_strings, raise_exception=True, exit_on_error=False)
|
|
78
|
-
# If 'ffmpeg.exe' is non-existent.
|
|
79
|
-
except FileNotFoundError:
|
|
80
|
-
# Check if full path to 'ffmpeg.exe' is just 'ffmpeg.exe'.
|
|
81
|
-
if self.ffmpeg_exe_path == self.ffmpeg_exe_name:
|
|
82
|
-
print_api('Will try temp folder...', raise_exception=False)
|
|
83
|
-
# Change to temp folder and try executing again.
|
|
84
|
-
self.change_to_temp_directory()
|
|
85
|
-
continue
|
|
86
|
-
|
|
87
|
-
print_api('Trying to download...', raise_exception=False)
|
|
88
|
-
create_directory(self.ffmpeg_release_directory_path)
|
|
89
|
-
self.download_ffmpeg_and_extract()
|
|
90
|
-
continue
|
|
91
|
-
|
|
92
|
-
# === At this point python exceptions are finished. ==========================
|
|
93
|
-
# If 'Invalid argument' was returned by 'ffmpeg' in the last line.
|
|
94
|
-
if 'Invalid argument' in result_lines[-1]:
|
|
95
|
-
print_api(result_lines[-1], message_type_error=True, color="red", exit_on_error=True)
|
|
96
|
-
|
|
97
|
-
# === Successful execution section ==========================================
|
|
98
|
-
string_pattern = 'video:*audio:*subtitle*'
|
|
99
|
-
# if 'video:' in result_lines[-1] and 'audio:' in result_lines[-1] and 'subtitle:' in result_lines[-1]:
|
|
100
|
-
if fnmatch.fnmatch(result_lines[-1], string_pattern):
|
|
101
|
-
print_api(f'FFmpeg finished successfully.', color="green")
|
|
102
|
-
|
|
103
|
-
# Since exceptions are finished, we can stop the while loop.
|
|
104
|
-
continue_loop = False
|
|
105
|
-
|
|
106
|
-
def convert_file(self, source_file_path: str, dest_file_path: str, overwrite: bool = False) -> None:
|
|
107
|
-
"""
|
|
108
|
-
The function converts source file to destination file. The source format is defined by the file extension
|
|
109
|
-
as well as destination file format defined by the destination file extension.
|
|
110
|
-
|
|
111
|
-
Example convert MP3 file to WAV:
|
|
112
|
-
convert_file(source_file_path=some_music.mp3, dest_file_path=converted_file.wav)
|
|
113
|
-
|
|
114
|
-
:param source_file_path: string, full file path to source file.
|
|
115
|
-
:param dest_file_path: string, full file path to destination file.
|
|
116
|
-
:param overwrite: boolean, set if destination file should be overwritten if it exists.
|
|
117
|
-
:return: None.
|
|
118
|
-
"""
|
|
119
|
-
|
|
120
|
-
cmd_list = ['-i', source_file_path, dest_file_path]
|
|
121
|
-
|
|
122
|
-
if overwrite:
|
|
123
|
-
cmd_list.append('-y')
|
|
124
|
-
|
|
125
|
-
self.execute_ffmpeg(cmd_list)
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
from atomicshop.process import execute_with_live_output
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def execute_pbtk(pbtk_path: str, file_path: str, target_directory: str) -> None:
|
|
5
|
-
"""
|
|
6
|
-
The function receives file path and target filesystem directory to extract the files.
|
|
7
|
-
|
|
8
|
-
:param pbtk_path: full path to pbtk file.
|
|
9
|
-
:param file_path: full path to binary file.
|
|
10
|
-
:param target_directory: The directory on the filesystem to extract files.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
cmd: str = f'python "{pbtk_path}" "{file_path}" "{target_directory}"'
|
|
14
|
-
print(f'Scanning: {file_path}')
|
|
15
|
-
|
|
16
|
-
output_list = execute_with_live_output(cmd=cmd)
|