warlock-manager 2.2.7__tar.gz → 2.2.9__tar.gz
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.
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/PKG-INFO +1 -1
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/pyproject.toml +1 -1
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/apps/base_app.py +20 -20
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/apps/steam_app.py +11 -11
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/config/ini_config.py +5 -5
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/app.py +5 -5
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/app_runner.py +6 -27
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/cmd.py +24 -23
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/download.py +3 -3
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/firewall.py +11 -11
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/java.py +3 -4
- warlock_manager-2.2.9/warlock_manager/libs/logger.py +70 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/meta.py +11 -1
- warlock_manager-2.2.9/warlock_manager/libs/proton.py +21 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/tui.py +3 -3
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/utils.py +2 -2
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/mods/base_mod.py +4 -4
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/mods/warlock_nexus_mod.py +3 -3
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/nexus/nexus.py +4 -8
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/services/base_service.py +87 -52
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/services/socket_service.py +14 -14
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager.egg-info/PKG-INFO +1 -1
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager.egg-info/SOURCES.txt +2 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/LICENSE +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/README.md +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/setup.cfg +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_app.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_base_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_base_service.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_cli_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_cli_formatter.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_cmd.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_config_key.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_ini_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_sensitive_data_filter.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_socket_service.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_unreal_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_unreal_config_ark_spawn_entities.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_unreal_save.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/tests/test_version.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/__init__.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/apps/__init__.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/apps/manual_app.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/config/__init__.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/config/base_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/config/cli_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/config/config_key.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/config/json_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/config/properties_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/config/unreal_config.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/formatters/__init__.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/formatters/cli_formatter.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/__init__.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/cache.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/get_wan_ip.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/ports.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/sensitive_data_filter.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/libs/version.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/mods/__init__.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/services/__init__.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/services/http_service.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager/services/rcon_service.py +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager.egg-info/dependency_links.txt +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager.egg-info/requires.txt +0 -0
- {warlock_manager-2.2.7 → warlock_manager-2.2.9}/warlock_manager.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import logging
|
|
3
2
|
import os
|
|
4
3
|
import shutil
|
|
5
4
|
import time
|
|
@@ -17,6 +16,7 @@ if TYPE_CHECKING:
|
|
|
17
16
|
from warlock_manager.libs.tui import prompt_yn, prompt_text
|
|
18
17
|
from warlock_manager.libs import utils
|
|
19
18
|
from warlock_manager.libs.ports import get_ports
|
|
19
|
+
from warlock_manager.libs.logger import logger
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class BaseApp(ABC):
|
|
@@ -116,7 +116,7 @@ class BaseApp(ABC):
|
|
|
116
116
|
elif config.path:
|
|
117
117
|
# Doesn't exist, (that's fine),
|
|
118
118
|
# but the directory structure should be available to make it more simple for saving
|
|
119
|
-
|
|
119
|
+
utils.ensure_file_parent_exists(config.path)
|
|
120
120
|
|
|
121
121
|
def save(self):
|
|
122
122
|
"""
|
|
@@ -150,7 +150,7 @@ class BaseApp(ABC):
|
|
|
150
150
|
if option in config.options:
|
|
151
151
|
return config.get_value(option)
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
logger.warning('Invalid option: %s, not present in game configuration!' % option)
|
|
154
154
|
return ''
|
|
155
155
|
|
|
156
156
|
def get_option_default(self, option: str) -> str:
|
|
@@ -163,7 +163,7 @@ class BaseApp(ABC):
|
|
|
163
163
|
if option in config.options:
|
|
164
164
|
return config.get_default(option)
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
logger.warning('Invalid option: %s, not present in game configuration!' % option)
|
|
167
167
|
return ''
|
|
168
168
|
|
|
169
169
|
def get_option_type(self, option: str) -> str:
|
|
@@ -176,7 +176,7 @@ class BaseApp(ABC):
|
|
|
176
176
|
if option in config.options:
|
|
177
177
|
return config.get_type(option)
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
logger.warning('Invalid option: %s, not present in game configuration!' % option)
|
|
180
180
|
return ''
|
|
181
181
|
|
|
182
182
|
def get_option_help(self, option: str) -> str:
|
|
@@ -189,7 +189,7 @@ class BaseApp(ABC):
|
|
|
189
189
|
if option in config.options:
|
|
190
190
|
return config.options[option].help
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
logger.warning('Invalid option: %s, not present in game configuration!' % option)
|
|
193
193
|
return ''
|
|
194
194
|
|
|
195
195
|
def option_value_updated(self, option: str, previous_value, new_value) -> bool | None:
|
|
@@ -226,18 +226,18 @@ class BaseApp(ABC):
|
|
|
226
226
|
post_result = self.option_value_updated(option, previous_value, new_value)
|
|
227
227
|
if post_result is True:
|
|
228
228
|
# Post-update either returned a successful operation or nothing at all, either is fine.
|
|
229
|
-
|
|
229
|
+
logger.info('Updated option %s to %s and ran post-update actions successfully' % (option, value))
|
|
230
230
|
return True
|
|
231
231
|
elif post_result is None:
|
|
232
|
-
|
|
233
|
-
|
|
232
|
+
logger.debug('Post-update returned None, this is fine as it indicates no post-actions taken')
|
|
233
|
+
logger.info('Updated option %s to %s' % (option, value))
|
|
234
234
|
return True
|
|
235
235
|
else:
|
|
236
236
|
# Post-update explictly returned False, this indicates a problem occurred.
|
|
237
|
-
|
|
237
|
+
logger.warning('Configuration saved, but unable to complete post-update actions!')
|
|
238
238
|
return False
|
|
239
239
|
|
|
240
|
-
|
|
240
|
+
logger.warning('Invalid option: %s, not present in game configuration!' % option)
|
|
241
241
|
return False
|
|
242
242
|
|
|
243
243
|
def get_option_options(self, option: str):
|
|
@@ -250,7 +250,7 @@ class BaseApp(ABC):
|
|
|
250
250
|
if option in config.options:
|
|
251
251
|
return config.get_options(option)
|
|
252
252
|
|
|
253
|
-
|
|
253
|
+
logger.warning('Invalid option: %s, not present in game configuration!' % option)
|
|
254
254
|
return []
|
|
255
255
|
|
|
256
256
|
def get_option_group(self, option: str):
|
|
@@ -263,7 +263,7 @@ class BaseApp(ABC):
|
|
|
263
263
|
if option in config.options:
|
|
264
264
|
return config.options[option].group
|
|
265
265
|
|
|
266
|
-
|
|
266
|
+
logger.warning('Invalid option: %s, not present in game configuration!' % option)
|
|
267
267
|
return 'Options'
|
|
268
268
|
|
|
269
269
|
def prompt_option(self, option: str):
|
|
@@ -376,11 +376,11 @@ class BaseApp(ABC):
|
|
|
376
376
|
"""
|
|
377
377
|
|
|
378
378
|
if action not in ['stop', 'restart', 'update']:
|
|
379
|
-
|
|
379
|
+
logger.error('Invalid action for delayed action: %s' % action)
|
|
380
380
|
return
|
|
381
381
|
|
|
382
382
|
if os.geteuid() != 0:
|
|
383
|
-
|
|
383
|
+
logger.error('Unable to %s game service unless run with sudo' % action)
|
|
384
384
|
return
|
|
385
385
|
|
|
386
386
|
msg = self.get_option_value('%s_delayed' % action)
|
|
@@ -391,7 +391,7 @@ class BaseApp(ABC):
|
|
|
391
391
|
services_running = []
|
|
392
392
|
services = self.get_services()
|
|
393
393
|
|
|
394
|
-
|
|
394
|
+
logger.info(
|
|
395
395
|
'Starting delayed %s action for all services, this gives current players up to an hour to log off safely' %
|
|
396
396
|
action
|
|
397
397
|
)
|
|
@@ -413,7 +413,7 @@ class BaseApp(ABC):
|
|
|
413
413
|
|
|
414
414
|
if player_count == 0 or player_count is None:
|
|
415
415
|
# No players online, stop the service
|
|
416
|
-
|
|
416
|
+
logger.info('Stopping %s as no players are online.' % service.service)
|
|
417
417
|
service.stop()
|
|
418
418
|
else:
|
|
419
419
|
# Still online, check to see if we should send a message
|
|
@@ -427,7 +427,7 @@ class BaseApp(ABC):
|
|
|
427
427
|
service.send_message(player_msg)
|
|
428
428
|
|
|
429
429
|
if minutes_left % 5 == 0 and minutes_left > 5:
|
|
430
|
-
|
|
430
|
+
logger.info('%s minutes remaining before %s.' % (str(minutes_left), action))
|
|
431
431
|
|
|
432
432
|
if not still_running or minutes_left <= 0:
|
|
433
433
|
# No services are running, stop the timer
|
|
@@ -443,7 +443,7 @@ class BaseApp(ABC):
|
|
|
443
443
|
# Now that all services have been stopped, restart any that were running before
|
|
444
444
|
for service in services:
|
|
445
445
|
if service.service in services_running:
|
|
446
|
-
|
|
446
|
+
logger.info('Starting %s' % service.service)
|
|
447
447
|
service.start()
|
|
448
448
|
|
|
449
449
|
def get_services(self) -> list['BaseService']:
|
|
@@ -659,7 +659,7 @@ class BaseApp(ABC):
|
|
|
659
659
|
for config in self.configs.values():
|
|
660
660
|
if config.path and os.path.exists(config.path):
|
|
661
661
|
os.remove(config.path)
|
|
662
|
-
|
|
662
|
+
logger.info('Removed config file for %s at %s' % (self.name, config.path))
|
|
663
663
|
|
|
664
664
|
# Cleanup directory structure
|
|
665
665
|
shutil.rmtree(os.path.join(utils.get_base_directory(), 'AppFiles'))
|
|
@@ -3,11 +3,11 @@ import re
|
|
|
3
3
|
import sys
|
|
4
4
|
import time
|
|
5
5
|
from abc import ABC
|
|
6
|
-
import logging
|
|
7
6
|
|
|
8
|
-
from .base_app import BaseApp
|
|
7
|
+
from warlock_manager.apps.base_app import BaseApp
|
|
9
8
|
from warlock_manager.libs.cmd import Cmd
|
|
10
9
|
from warlock_manager.libs import utils
|
|
10
|
+
from warlock_manager.libs.logger import logger
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def guess_steamcmd_path() -> str:
|
|
@@ -21,7 +21,7 @@ def guess_steamcmd_path() -> str:
|
|
|
21
21
|
)
|
|
22
22
|
for path in paths:
|
|
23
23
|
if os.path.exists(path):
|
|
24
|
-
|
|
24
|
+
logger.debug('Found steamcmd at %s' % path)
|
|
25
25
|
return path
|
|
26
26
|
raise FileNotFoundError('steamcmd not found in common locations. Please ensure steamcmd is installed.')
|
|
27
27
|
|
|
@@ -290,11 +290,11 @@ class SteamApp(BaseApp, ABC):
|
|
|
290
290
|
return []
|
|
291
291
|
|
|
292
292
|
if 'depots' not in info:
|
|
293
|
-
|
|
293
|
+
logger.warning(f"No depot information found for app {self.steam_id}.")
|
|
294
294
|
return []
|
|
295
295
|
|
|
296
296
|
if 'branches' not in info['depots']:
|
|
297
|
-
|
|
297
|
+
logger.warning(f"No branch information found for app {self.steam_id}.")
|
|
298
298
|
return []
|
|
299
299
|
|
|
300
300
|
return list(info['depots']['branches'].keys())
|
|
@@ -366,18 +366,18 @@ class SteamApp(BaseApp, ABC):
|
|
|
366
366
|
|
|
367
367
|
:return:
|
|
368
368
|
"""
|
|
369
|
-
|
|
369
|
+
logger.info('Updating game %s via Steam...' % self.name)
|
|
370
370
|
# Stop any running services before updating
|
|
371
371
|
services = []
|
|
372
372
|
for service in self.get_services():
|
|
373
373
|
if service.is_running() or service.is_starting():
|
|
374
|
-
|
|
375
|
-
services.append(service
|
|
374
|
+
logger.info('Stopping service %s for update...' % service.service)
|
|
375
|
+
services.append(service)
|
|
376
376
|
service.stop()
|
|
377
377
|
|
|
378
378
|
if len(services) > 0:
|
|
379
379
|
# Wait for all services to stop, may take 5 minutes if players are online.
|
|
380
|
-
|
|
380
|
+
logger.info('Waiting up to 5 minutes for all services to stop...')
|
|
381
381
|
counter = 0
|
|
382
382
|
while counter < 30:
|
|
383
383
|
all_stopped = True
|
|
@@ -390,7 +390,7 @@ class SteamApp(BaseApp, ABC):
|
|
|
390
390
|
break
|
|
391
391
|
time.sleep(10)
|
|
392
392
|
else:
|
|
393
|
-
|
|
393
|
+
logger.info('No running services found, proceeding with update...')
|
|
394
394
|
|
|
395
395
|
cmd = Cmd([
|
|
396
396
|
guess_steamcmd_path(),
|
|
@@ -423,7 +423,7 @@ class SteamApp(BaseApp, ABC):
|
|
|
423
423
|
self.post_update()
|
|
424
424
|
|
|
425
425
|
if len(services) > 0:
|
|
426
|
-
|
|
426
|
+
logger.info('Update completed, restarting previously running services...')
|
|
427
427
|
for service in services:
|
|
428
428
|
service.start()
|
|
429
429
|
|
|
@@ -3,9 +3,9 @@ from typing import Union
|
|
|
3
3
|
import configparser
|
|
4
4
|
import tempfile
|
|
5
5
|
import os
|
|
6
|
-
import logging
|
|
7
6
|
|
|
8
7
|
from warlock_manager.config.base_config import BaseConfig
|
|
8
|
+
from warlock_manager.libs.logger import logger
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class INIConfig(BaseConfig):
|
|
@@ -65,13 +65,13 @@ class INIConfig(BaseConfig):
|
|
|
65
65
|
section = self.group
|
|
66
66
|
|
|
67
67
|
if section is None:
|
|
68
|
-
|
|
68
|
+
logger.error(
|
|
69
69
|
'Cannot set INI config value for option %s because it does not have a section defined!' %
|
|
70
70
|
name
|
|
71
71
|
)
|
|
72
72
|
return
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
logger.debug('Setting INI config value: %s => [%s] %s = %s' % (name, section, opt.key, str_value))
|
|
75
75
|
|
|
76
76
|
# Escape '%' characters that may be present
|
|
77
77
|
str_value = str_value.replace('%', '%%')
|
|
@@ -118,10 +118,10 @@ class INIConfig(BaseConfig):
|
|
|
118
118
|
if self.spoof_group:
|
|
119
119
|
with open(self.path, 'r') as f:
|
|
120
120
|
self.parser.read_string('[%s]\n' % self.group + f.read())
|
|
121
|
-
|
|
121
|
+
logger.debug('Loaded INI config %s with spoofed group: %s' % (self.path, self.group))
|
|
122
122
|
else:
|
|
123
123
|
self.parser.read(self.path)
|
|
124
|
-
|
|
124
|
+
logger.debug('Loaded INI config: %s' % self.path)
|
|
125
125
|
|
|
126
126
|
def save(self):
|
|
127
127
|
"""
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import os
|
|
3
2
|
import sys
|
|
4
3
|
|
|
@@ -9,6 +8,7 @@ from warlock_manager.libs.tui import print_header, Table, print_subheader, promp
|
|
|
9
8
|
prompt_long_text
|
|
10
9
|
from warlock_manager.apps.base_app import BaseApp
|
|
11
10
|
from warlock_manager.services.base_service import BaseService
|
|
11
|
+
from warlock_manager.libs.logger import logger
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
ICON_ENABLED = '✅'
|
|
@@ -223,11 +223,11 @@ def menu_mods(source: BaseService):
|
|
|
223
223
|
if add_help is not None:
|
|
224
224
|
add_help = add_help.strip().split('\n')[0].strip()
|
|
225
225
|
else:
|
|
226
|
-
|
|
226
|
+
logger.debug('Mod handler does not provide help for mods search.')
|
|
227
227
|
else:
|
|
228
|
-
|
|
228
|
+
logger.debug('Mod handler does not support mods search.')
|
|
229
229
|
else:
|
|
230
|
-
|
|
230
|
+
logger.error('Mod handler is not available for this application.')
|
|
231
231
|
return
|
|
232
232
|
|
|
233
233
|
counter = 0
|
|
@@ -435,7 +435,7 @@ def menu_service(service: BaseService):
|
|
|
435
435
|
|
|
436
436
|
if opt.isdigit() and 1 <= int(opt) <= counter:
|
|
437
437
|
if service.is_running():
|
|
438
|
-
|
|
438
|
+
logger.warning('Cannot configure options for a service while it is running.')
|
|
439
439
|
else:
|
|
440
440
|
menu_config_option(service, options_ordered[int(opt) - 1])
|
|
441
441
|
elif opt == 'b':
|
|
@@ -1,31 +1,14 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
-
import inspect
|
|
4
3
|
import sys
|
|
5
4
|
import typer
|
|
6
5
|
from typing import Annotated
|
|
7
6
|
from warlock_manager.apps.base_app import BaseApp
|
|
8
7
|
from warlock_manager.services.base_service import BaseService
|
|
9
|
-
from warlock_manager.libs.sensitive_data_filter import sensitive_data_filter
|
|
10
8
|
from warlock_manager.libs.app import default_menu_main
|
|
11
9
|
from warlock_manager.libs.meta import get_meta
|
|
12
10
|
from warlock_manager.nexus.nexus import Nexus
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class ClassNameFilter(logging.Filter):
|
|
16
|
-
def filter(self, record):
|
|
17
|
-
# Try to get the class name from the call stack
|
|
18
|
-
frame = inspect.currentframe()
|
|
19
|
-
while frame:
|
|
20
|
-
if 'self' in frame.f_locals:
|
|
21
|
-
class_name = frame.f_locals['self'].__class__.__name__
|
|
22
|
-
if class_name not in ['ClassNameFilter', 'RootLogger']:
|
|
23
|
-
record.classname = frame.f_locals['self'].__class__.__name__
|
|
24
|
-
break
|
|
25
|
-
frame = frame.f_back
|
|
26
|
-
else:
|
|
27
|
-
record.classname = ''
|
|
28
|
-
return True
|
|
11
|
+
from warlock_manager.libs.logger import logger
|
|
29
12
|
|
|
30
13
|
|
|
31
14
|
def app_runner(game: BaseApp):
|
|
@@ -54,6 +37,7 @@ def app_runner(game: BaseApp):
|
|
|
54
37
|
:param value:
|
|
55
38
|
:return: BaseService | None
|
|
56
39
|
"""
|
|
40
|
+
logger.debug('Resolving service: %s' % value)
|
|
57
41
|
if value is None:
|
|
58
42
|
return None
|
|
59
43
|
services = game.get_services()
|
|
@@ -127,16 +111,10 @@ def app_runner(game: BaseApp):
|
|
|
127
111
|
debug: arg_debug = False
|
|
128
112
|
):
|
|
129
113
|
log_level = logging.DEBUG if debug else logging.INFO
|
|
130
|
-
|
|
131
|
-
level=log_level,
|
|
132
|
-
format='%(asctime)s [%(levelname)s] %(classname)s.%(funcName)s: %(message)s',
|
|
133
|
-
force=True
|
|
134
|
-
)
|
|
135
|
-
logging.getLogger().addFilter(ClassNameFilter())
|
|
136
|
-
logging.getLogger().addFilter(sensitive_data_filter)
|
|
114
|
+
logger.setLevel(log_level)
|
|
137
115
|
|
|
138
116
|
if debug:
|
|
139
|
-
|
|
117
|
+
logger.debug('Debug logging enabled')
|
|
140
118
|
|
|
141
119
|
# If no subcommand was provided, call main()
|
|
142
120
|
if ctx.invoked_subcommand is None:
|
|
@@ -257,7 +235,7 @@ def app_runner(game: BaseApp):
|
|
|
257
235
|
sys.exit(0 if service.backup(max_backups) else 1)
|
|
258
236
|
else:
|
|
259
237
|
if len(game.get_services()) == 0:
|
|
260
|
-
|
|
238
|
+
logger.warning('No services are available for backup, nothing to do.')
|
|
261
239
|
sys.exit(1)
|
|
262
240
|
success = True
|
|
263
241
|
for svc in game.get_services():
|
|
@@ -394,6 +372,7 @@ def app_runner(game: BaseApp):
|
|
|
394
372
|
:param service: BaseService | None
|
|
395
373
|
:return:
|
|
396
374
|
"""
|
|
375
|
+
logger.debug('Running get_metrics()')
|
|
397
376
|
nexus = Nexus()
|
|
398
377
|
if service and isinstance(service, BaseService):
|
|
399
378
|
services: list[BaseService] = [service]
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import subprocess
|
|
3
3
|
import json
|
|
4
|
-
import logging
|
|
5
4
|
import time
|
|
6
5
|
import pwd
|
|
7
6
|
|
|
8
7
|
from warlock_manager.libs import cache
|
|
8
|
+
from warlock_manager.libs.logger import logger
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class CmdFakeResponse:
|
|
@@ -223,13 +223,13 @@ class Cmd:
|
|
|
223
223
|
:return:
|
|
224
224
|
"""
|
|
225
225
|
if self.result is None:
|
|
226
|
-
|
|
226
|
+
logger.debug('Running command: %s' % ' '.join(self.cmd))
|
|
227
227
|
if self.memory_cacheable is not False:
|
|
228
228
|
key = ' '.join(self.cmd)
|
|
229
229
|
if key in self._memory_cache:
|
|
230
|
-
cached_time, cached = Cmd._memory_cache[key]
|
|
230
|
+
cached_time, cached, code = Cmd._memory_cache[key]
|
|
231
231
|
if cached_time + self.memory_cacheable >= time.time():
|
|
232
|
-
|
|
232
|
+
logger.debug('Using memory cached result instead')
|
|
233
233
|
self.result = CmdFakeResponse(
|
|
234
234
|
cached if self.uses == 'stdout' else '',
|
|
235
235
|
cached if self.uses == 'stderr' else '',
|
|
@@ -240,7 +240,7 @@ class Cmd:
|
|
|
240
240
|
if self.cacheable is not False:
|
|
241
241
|
cached = self.try_cache()
|
|
242
242
|
if cached is not None:
|
|
243
|
-
|
|
243
|
+
logger.debug('Using cached result instead')
|
|
244
244
|
self.result = CmdFakeResponse(
|
|
245
245
|
cached if self.uses == 'stdout' else '',
|
|
246
246
|
cached if self.uses == 'stderr' else '',
|
|
@@ -263,22 +263,23 @@ class Cmd:
|
|
|
263
263
|
self.result = CmdFakeResponse('', str(e), 1)
|
|
264
264
|
finally:
|
|
265
265
|
if self.result.stdout:
|
|
266
|
-
|
|
266
|
+
logger.debug('STDOUT: %s' % self.result.stdout.strip())
|
|
267
267
|
if self.result.stderr:
|
|
268
|
-
|
|
269
|
-
|
|
268
|
+
logger.debug('STDERR: %s' % self.result.stderr.strip())
|
|
269
|
+
logger.debug('Return code: %d' % self.result.returncode)
|
|
270
|
+
|
|
271
|
+
# Cache all responses to memory if requested, saves time on failed lookup checks.
|
|
272
|
+
if self.memory_cacheable is not False:
|
|
273
|
+
key = ' '.join(self.cmd)
|
|
274
|
+
if self.uses == 'stdout':
|
|
275
|
+
Cmd._memory_cache[key] = (time.time(), self.result.stdout, self.result.returncode)
|
|
276
|
+
elif self.uses == 'stderr':
|
|
277
|
+
Cmd._memory_cache[key] = (time.time(), self.result.stderr, self.result.returncode)
|
|
278
|
+
else:
|
|
279
|
+
logger.warning('Attempting to cache command output without capturing it. This is not supported!')
|
|
270
280
|
|
|
271
281
|
if self.result.returncode == 0:
|
|
272
|
-
#
|
|
273
|
-
if self.memory_cacheable is not False:
|
|
274
|
-
key = ' '.join(self.cmd)
|
|
275
|
-
if self.uses == 'stdout':
|
|
276
|
-
Cmd._memory_cache[key] = (time.time(), self.result.stdout)
|
|
277
|
-
elif self.uses == 'stderr':
|
|
278
|
-
Cmd._memory_cache[key] = (time.time(), self.result.stderr)
|
|
279
|
-
else:
|
|
280
|
-
logging.warning('Attempting to cache command output without capturing it. This is not supported!')
|
|
281
|
-
|
|
282
|
+
# Successful executions can be cached to disk
|
|
282
283
|
if self.cacheable is not False:
|
|
283
284
|
# Do we save stdout or stderr?
|
|
284
285
|
if self.uses == 'stdout':
|
|
@@ -286,7 +287,7 @@ class Cmd:
|
|
|
286
287
|
elif self.uses == 'stderr':
|
|
287
288
|
cache.save_cache(' '.join(self.cmd), self.result.stderr)
|
|
288
289
|
else:
|
|
289
|
-
|
|
290
|
+
logger.warning('Attempting to cache command output without capturing it. This is not supported!')
|
|
290
291
|
|
|
291
292
|
return self.result
|
|
292
293
|
|
|
@@ -323,10 +324,10 @@ class PipeCmd(Cmd):
|
|
|
323
324
|
if self.result is None:
|
|
324
325
|
|
|
325
326
|
if self.cacheable is not False:
|
|
326
|
-
|
|
327
|
+
logger.warning('Piped commands cannot be cached!')
|
|
327
328
|
|
|
328
329
|
try:
|
|
329
|
-
|
|
330
|
+
logger.debug('Running piped command: %s' % ' '.join(self.cmd))
|
|
330
331
|
self.result = subprocess.Popen(
|
|
331
332
|
self.cmd,
|
|
332
333
|
cwd=self._cwd,
|
|
@@ -355,10 +356,10 @@ class BackgroundCmd(Cmd):
|
|
|
355
356
|
if self.result is None:
|
|
356
357
|
|
|
357
358
|
if self.cacheable is not False:
|
|
358
|
-
|
|
359
|
+
logger.warning('Background commands cannot be cached!')
|
|
359
360
|
|
|
360
361
|
try:
|
|
361
|
-
|
|
362
|
+
logger.debug('Running background command: %s' % ' '.join(self.cmd))
|
|
362
363
|
self.result = subprocess.Popen(
|
|
363
364
|
self.cmd,
|
|
364
365
|
cwd=self._cwd,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import requests
|
|
3
2
|
import json
|
|
4
3
|
from warlock_manager.libs import utils
|
|
5
4
|
from warlock_manager.libs import cache
|
|
6
5
|
from warlock_manager.libs.meta import get_meta
|
|
6
|
+
from warlock_manager.libs.logger import logger
|
|
7
7
|
|
|
8
8
|
# "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
9
9
|
USER_AGENT = 'Warlock Manager/%s (warlock.nexus) <staff@bitsnbytes.dev>' % get_meta()['version']
|
|
@@ -18,7 +18,7 @@ def download_file(url: str, destination: str):
|
|
|
18
18
|
:param destination: The local file path to save the downloaded file to
|
|
19
19
|
:return:
|
|
20
20
|
"""
|
|
21
|
-
|
|
21
|
+
logger.debug('Downloading file %s to %s' % (url, destination))
|
|
22
22
|
# Ensure the target directory exists
|
|
23
23
|
utils.ensure_file_parent_exists(destination)
|
|
24
24
|
|
|
@@ -44,7 +44,7 @@ def download_json(url: str) -> dict:
|
|
|
44
44
|
:param url: The URL to download from
|
|
45
45
|
:return: The JSON data as a dictionary
|
|
46
46
|
"""
|
|
47
|
-
|
|
47
|
+
logger.debug('Downloading JSON %s' % url)
|
|
48
48
|
|
|
49
49
|
# Try the cache first
|
|
50
50
|
cached = cache.get_cache(url)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from warlock_manager.libs.cmd import Cmd
|
|
2
|
-
import
|
|
2
|
+
from warlock_manager.libs.logger import logger
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class Firewall:
|
|
@@ -92,11 +92,11 @@ class Firewall:
|
|
|
92
92
|
"""
|
|
93
93
|
|
|
94
94
|
if port <= 0 or port >= 65536:
|
|
95
|
-
|
|
95
|
+
logger.error(f"Invalid port number: {port}")
|
|
96
96
|
return False
|
|
97
97
|
|
|
98
98
|
if protocol.lower() not in ['tcp', 'udp']:
|
|
99
|
-
|
|
99
|
+
logger.error(f"Invalid protocol: {protocol}")
|
|
100
100
|
return False
|
|
101
101
|
|
|
102
102
|
firewall = cls.get_available()
|
|
@@ -104,20 +104,20 @@ class Firewall:
|
|
|
104
104
|
if firewall == 'ufw':
|
|
105
105
|
# UFW requires the protocol to be all lowercase.
|
|
106
106
|
protocol = protocol.lower()
|
|
107
|
-
|
|
107
|
+
logger.info(f"Allowing {port}/{protocol} via UFW")
|
|
108
108
|
cmd = Cmd(['ufw', 'allow', f'{port}/{protocol}'])
|
|
109
109
|
if comment:
|
|
110
110
|
cmd.extend(['comment', comment])
|
|
111
111
|
return cmd.success
|
|
112
112
|
|
|
113
113
|
elif firewall == 'firewalld':
|
|
114
|
-
|
|
114
|
+
logger.info(f"Allowing {port}/{protocol} via Firewalld")
|
|
115
115
|
if Cmd(['firewall-cmd', '--permanent', '--add-port', f'{port}/{protocol}']).success:
|
|
116
116
|
Cmd(['firewall-cmd', '--reload']).run()
|
|
117
117
|
return True
|
|
118
118
|
|
|
119
119
|
elif firewall == 'iptables':
|
|
120
|
-
|
|
120
|
+
logger.info(f"Allowing {port}/{protocol} via iptables")
|
|
121
121
|
cmd = Cmd(['iptables', '-A', 'INPUT', '-p', protocol, '--dport', str(port), '-j', 'ACCEPT'])
|
|
122
122
|
if comment:
|
|
123
123
|
cmd.extend(['-m', 'comment', '--comment', comment])
|
|
@@ -126,7 +126,7 @@ class Firewall:
|
|
|
126
126
|
return True
|
|
127
127
|
|
|
128
128
|
else:
|
|
129
|
-
|
|
129
|
+
logger.error('No supported firewall found on the system.')
|
|
130
130
|
|
|
131
131
|
return False
|
|
132
132
|
|
|
@@ -142,11 +142,11 @@ class Firewall:
|
|
|
142
142
|
"""
|
|
143
143
|
|
|
144
144
|
if port <= 0 or port >= 65536:
|
|
145
|
-
|
|
145
|
+
logger.error(f"Invalid port number: {port}")
|
|
146
146
|
return False
|
|
147
147
|
|
|
148
148
|
if protocol.lower() not in ['tcp', 'udp']:
|
|
149
|
-
|
|
149
|
+
logger.error(f"Invalid protocol: {protocol}")
|
|
150
150
|
return False
|
|
151
151
|
|
|
152
152
|
firewall = cls.get_available()
|
|
@@ -165,7 +165,7 @@ class Firewall:
|
|
|
165
165
|
return True
|
|
166
166
|
|
|
167
167
|
else:
|
|
168
|
-
|
|
168
|
+
logger.error('No supported firewall found on the system.')
|
|
169
169
|
|
|
170
170
|
return False
|
|
171
171
|
|
|
@@ -219,5 +219,5 @@ class Firewall:
|
|
|
219
219
|
return False
|
|
220
220
|
|
|
221
221
|
else:
|
|
222
|
-
|
|
222
|
+
logger.error('No supported firewall found on the system.')
|
|
223
223
|
return True # No firewall means it's probably enabled by default, so we return true.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
|
|
3
1
|
from warlock_manager.libs.version import extract_version_from_string, parse_version
|
|
4
2
|
from warlock_manager.libs.cmd import Cmd
|
|
3
|
+
from warlock_manager.libs.logger import logger
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
def get_java_paths() -> list[str]:
|
|
@@ -50,7 +49,7 @@ def _check_java_versions(java_paths: list[str], target_version: int) -> str | No
|
|
|
50
49
|
:param target_version: The major Java version to find
|
|
51
50
|
:return: The path to the matching Java executable, or None if not found
|
|
52
51
|
"""
|
|
53
|
-
|
|
52
|
+
logger.debug('Searching for Java version %d' % target_version)
|
|
54
53
|
for java_path in java_paths:
|
|
55
54
|
result = Cmd([java_path, '-version'])
|
|
56
55
|
# Java version information is typically printed to stderr, so we need to use that instead of stdout.
|
|
@@ -62,7 +61,7 @@ def _check_java_versions(java_paths: list[str], target_version: int) -> str | No
|
|
|
62
61
|
# Use the version library to parse this version string.
|
|
63
62
|
version_str = extract_version_from_string(version_str)
|
|
64
63
|
version = parse_version(version_str)
|
|
65
|
-
|
|
64
|
+
logger.debug('%s => %s' % (java_path, version))
|
|
66
65
|
if version.major == 1:
|
|
67
66
|
# For Java 8 and earlier, the version string starts with "1.", so we need to check the minor version
|
|
68
67
|
if version.minor == target_version:
|