meerschaum 2.3.0rc3__py3-none-any.whl → 2.3.1__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.
- meerschaum/__init__.py +2 -3
- meerschaum/_internal/arguments/__init__.py +1 -1
- meerschaum/_internal/arguments/_parse_arguments.py +33 -22
- meerschaum/_internal/arguments/_parser.py +4 -7
- meerschaum/_internal/docs/index.py +265 -8
- meerschaum/_internal/entry.py +42 -4
- meerschaum/_internal/shell/Shell.py +84 -72
- meerschaum/actions/__init__.py +21 -11
- meerschaum/actions/show.py +5 -5
- meerschaum/actions/start.py +71 -1
- meerschaum/api/routes/_actions.py +48 -1
- meerschaum/config/_paths.py +1 -0
- meerschaum/config/_version.py +1 -1
- meerschaum/config/static/__init__.py +2 -0
- meerschaum/connectors/__init__.py +1 -2
- meerschaum/connectors/api/APIConnector.py +6 -1
- meerschaum/connectors/api/_actions.py +77 -1
- meerschaum/connectors/api/_pipes.py +85 -84
- meerschaum/jobs/_Job.py +38 -6
- meerschaum/jobs/__init__.py +5 -3
- meerschaum/jobs/{_SystemdExecutor.py → systemd.py} +39 -22
- meerschaum/plugins/_Plugin.py +1 -1
- meerschaum/plugins/__init__.py +2 -1
- meerschaum/utils/daemon/StdinFile.py +1 -0
- meerschaum/utils/daemon/_names.py +14 -12
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/METADATA +1 -1
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/RECORD +33 -34
- meerschaum/jobs/_LocalExecutor.py +0 -88
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/LICENSE +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/NOTICE +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/WHEEL +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/top_level.txt +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/zip-safe +0 -0
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
9
9
|
import os
|
10
10
|
from copy import deepcopy
|
11
11
|
from itertools import chain
|
12
|
+
import shlex
|
12
13
|
|
13
14
|
from meerschaum.utils.typing import Union, SuccessTuple, Any, Callable, Optional, List, Dict
|
14
15
|
from meerschaum.utils.packages import attempt_import
|
@@ -31,12 +32,15 @@ from meerschaum._internal.shell.ValidAutoSuggest import ValidAutoSuggest
|
|
31
32
|
from meerschaum._internal.shell.ShellCompleter import ShellCompleter
|
32
33
|
_clear_screen = get_config('shell', 'clear_screen', patch=True)
|
33
34
|
from meerschaum.utils.misc import string_width, remove_ansi
|
35
|
+
from meerschaum.utils.warnings import warn
|
34
36
|
from meerschaum.jobs import get_executor_keys_from_context
|
35
37
|
from meerschaum.config.static import STATIC_CONFIG
|
36
38
|
from meerschaum._internal.arguments._parse_arguments import (
|
37
39
|
split_chained_sysargs,
|
40
|
+
split_pipeline_sysargs,
|
38
41
|
parse_arguments,
|
39
42
|
parse_line,
|
43
|
+
parse_dict_to_sysargs,
|
40
44
|
)
|
41
45
|
|
42
46
|
patch = True
|
@@ -73,6 +77,8 @@ reserved_completers = {
|
|
73
77
|
shell_attrs = {}
|
74
78
|
AND_KEY: str = STATIC_CONFIG['system']['arguments']['and_key']
|
75
79
|
ESCAPED_AND_KEY: str = STATIC_CONFIG['system']['arguments']['escaped_and_key']
|
80
|
+
PIPELINE_KEY: str = STATIC_CONFIG['system']['arguments']['pipeline_key']
|
81
|
+
ESCAPED_PIPELINE_KEY: str = STATIC_CONFIG['system']['arguments']['escaped_pipeline_key']
|
76
82
|
|
77
83
|
def _insert_shell_actions(
|
78
84
|
_shell: Optional['Shell'] = None,
|
@@ -173,7 +179,6 @@ def _check_complete_keys(line: str) -> Optional[List[str]]:
|
|
173
179
|
|
174
180
|
### TODO Find out arg possibilities
|
175
181
|
possibilities = []
|
176
|
-
# last_word = line.split(' ')[-1]
|
177
182
|
last_word = line.rstrip(' ').split(' ')[-1]
|
178
183
|
|
179
184
|
if last_word.startswith('-'):
|
@@ -485,6 +490,9 @@ class Shell(cmd.Cmd):
|
|
485
490
|
### make a backup of line for later
|
486
491
|
original_line = deepcopy(line)
|
487
492
|
|
493
|
+
### Escape backslashes to allow for multi-line input.
|
494
|
+
line = line.replace('\\\n', ' ')
|
495
|
+
|
488
496
|
### cmd2 support: check if command exists
|
489
497
|
try:
|
490
498
|
command = line.command
|
@@ -515,48 +523,71 @@ class Shell(cmd.Cmd):
|
|
515
523
|
return "help " + line[len(help_token):]
|
516
524
|
|
517
525
|
from meerschaum._internal.arguments import parse_line
|
518
|
-
|
519
|
-
|
526
|
+
try:
|
527
|
+
sysargs = shlex.split(line)
|
528
|
+
except ValueError as e:
|
529
|
+
warn(e, stack=False)
|
530
|
+
return ""
|
531
|
+
|
532
|
+
sysargs, pipeline_args = split_pipeline_sysargs(sysargs)
|
533
|
+
chained_sysargs = split_chained_sysargs(sysargs)
|
534
|
+
chained_kwargs = [
|
535
|
+
parse_arguments(_sysargs)
|
536
|
+
for _sysargs in chained_sysargs
|
537
|
+
]
|
538
|
+
|
539
|
+
if '--help' in sysargs or '-h' in sysargs:
|
520
540
|
from meerschaum._internal.arguments._parser import parse_help
|
521
|
-
parse_help(
|
541
|
+
parse_help(sysargs)
|
522
542
|
return ""
|
523
543
|
|
544
|
+
patch_args: Dict[str, Any] = {}
|
545
|
+
|
524
546
|
### NOTE: pass `shell` flag in case actions need to distinguish between
|
525
547
|
### being run on the command line and being run in the shell
|
526
|
-
|
527
|
-
|
548
|
+
patch_args.update({
|
549
|
+
'shell': True,
|
550
|
+
'line': line,
|
551
|
+
})
|
552
|
+
patches: List[Dict[str, Any]] = [{} for _ in chained_kwargs]
|
528
553
|
|
529
554
|
### if debug is not set on the command line,
|
530
555
|
### default to shell setting
|
531
|
-
|
532
|
-
|
556
|
+
for kwargs in chained_kwargs:
|
557
|
+
if not kwargs.get('debug', False):
|
558
|
+
kwargs['debug'] = shell_attrs['debug']
|
533
559
|
|
534
560
|
### Make sure an action was provided.
|
535
|
-
if
|
561
|
+
if (
|
562
|
+
not chained_kwargs
|
563
|
+
or not chained_kwargs[0].get('action', None)
|
564
|
+
):
|
536
565
|
self.emptyline()
|
537
566
|
return ''
|
538
567
|
|
539
568
|
### Strip a leading 'mrsm' if it's provided.
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
569
|
+
for kwargs in chained_kwargs:
|
570
|
+
if kwargs['action'][0] == 'mrsm':
|
571
|
+
kwargs['action'] = kwargs['action'][1:]
|
572
|
+
if not kwargs['action']:
|
573
|
+
self.emptyline()
|
574
|
+
return ''
|
545
575
|
|
546
576
|
### If we don't recognize the action,
|
547
577
|
### make it a shell action.
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
578
|
+
### TODO: make this work for chained actions
|
579
|
+
def _get_main_action_name(kwargs):
|
580
|
+
from meerschaum.actions import get_main_action_name
|
581
|
+
main_action_name = get_main_action_name(kwargs['action'])
|
582
|
+
if main_action_name is None:
|
583
|
+
if not hasattr(self, 'do_' + kwargs['action'][0]):
|
584
|
+
kwargs['action'].insert(0, 'sh')
|
585
|
+
main_action_name = 'sh'
|
586
|
+
else:
|
587
|
+
main_action_name = kwargs['action'][0]
|
588
|
+
return main_action_name
|
589
|
+
|
590
|
+
def _add_flag_to_kwargs(kwargs, i, key, shell_key=None):
|
560
591
|
shell_key = shell_key or key
|
561
592
|
shell_value = remove_ansi(shell_attrs.get(shell_key) or '')
|
562
593
|
if key == 'mrsm_instance':
|
@@ -568,68 +599,49 @@ class Shell(cmd.Cmd):
|
|
568
599
|
else:
|
569
600
|
default_value = None
|
570
601
|
|
571
|
-
if shell_value == default_value:
|
602
|
+
if key in kwargs or shell_value == default_value:
|
572
603
|
return
|
573
604
|
|
574
|
-
|
575
|
-
kwargs = parse_arguments(sysargs)
|
576
|
-
if key in kwargs:
|
577
|
-
continue
|
578
|
-
sysargs.extend([flag, value])
|
579
|
-
|
580
|
-
args['sysargs'] = list(
|
581
|
-
chain.from_iterable(
|
582
|
-
sub_sysargs + [AND_KEY]
|
583
|
-
for sub_sysargs in chained_sysargs
|
584
|
-
)
|
585
|
-
)[:-1]
|
586
|
-
|
605
|
+
patches[i][key] = shell_value
|
587
606
|
|
588
607
|
### if no instance is provided, use current shell default,
|
589
608
|
### but not for the 'api' command (to avoid recursion)
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
args['mrsm_instance'] = mrsm_instance
|
595
|
-
_add_flag_to_sysargs(
|
596
|
-
chained_sysargs, 'mrsm_instance', mrsm_instance, '-i', 'instance_keys',
|
597
|
-
)
|
598
|
-
_add_flag_to_sysargs(
|
599
|
-
chained_filtered_sysargs, 'mrsm_instance', mrsm_instance, '-i', 'instance_keys',
|
600
|
-
)
|
601
|
-
|
602
|
-
repo_keys = str(shell_attrs['repo_keys'])
|
603
|
-
args['repository'] = repo_keys
|
604
|
-
_add_flag_to_sysargs(
|
605
|
-
chained_sysargs, 'repository', repo_keys, '-r', 'repo_keys',
|
606
|
-
)
|
607
|
-
_add_flag_to_sysargs(
|
608
|
-
chained_filtered_sysargs, 'repository', repo_keys, '-r', 'repo_keys',
|
609
|
-
)
|
609
|
+
for i, kwargs in enumerate(chained_kwargs):
|
610
|
+
main_action_name = _get_main_action_name(kwargs)
|
611
|
+
if main_action_name == 'api':
|
612
|
+
continue
|
610
613
|
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
chained_sysargs, 'executor_keys', executor_keys, '-e',
|
615
|
-
)
|
616
|
-
_add_flag_to_sysargs(
|
617
|
-
chained_filtered_sysargs, 'executor_keys', executor_keys, '-e',
|
618
|
-
)
|
614
|
+
_add_flag_to_kwargs(kwargs, i, 'mrsm_instance', shell_key='instance_keys')
|
615
|
+
_add_flag_to_kwargs(kwargs, i, 'repository', shell_key='repo_keys')
|
616
|
+
_add_flag_to_kwargs(kwargs, i, 'executor_keys')
|
619
617
|
|
620
618
|
### parse out empty strings
|
621
|
-
if
|
619
|
+
if chained_kwargs[0]['action'][0].strip("\"'") == '':
|
622
620
|
self.emptyline()
|
623
621
|
return ""
|
624
622
|
|
625
|
-
positional_only = (
|
623
|
+
positional_only = (_get_main_action_name(chained_kwargs[0]) not in shell_attrs['_actions'])
|
626
624
|
if positional_only:
|
627
625
|
return original_line
|
628
626
|
|
629
|
-
|
627
|
+
### Apply patch to all kwargs.
|
628
|
+
for i, kwargs in enumerate([_ for _ in chained_kwargs]):
|
629
|
+
kwargs.update(patches[i])
|
630
|
+
|
631
|
+
from meerschaum._internal.entry import entry_with_args, entry
|
632
|
+
sysargs_to_execute = []
|
633
|
+
for i, kwargs in enumerate(chained_kwargs):
|
634
|
+
step_kwargs = {k: v for k, v in kwargs.items() if k != 'line'}
|
635
|
+
step_sysargs = parse_dict_to_sysargs(step_kwargs)
|
636
|
+
sysargs_to_execute.extend(step_sysargs)
|
637
|
+
sysargs_to_execute.append(AND_KEY)
|
638
|
+
|
639
|
+
sysargs_to_execute = sysargs_to_execute[:-1] + (
|
640
|
+
([':'] + pipeline_args) if pipeline_args else []
|
641
|
+
)
|
630
642
|
|
631
643
|
try:
|
632
|
-
success_tuple =
|
644
|
+
success_tuple = entry(sysargs_to_execute, _patch_args=patch_args)
|
633
645
|
except Exception as e:
|
634
646
|
success_tuple = False, str(e)
|
635
647
|
|
meerschaum/actions/__init__.py
CHANGED
@@ -11,6 +11,16 @@ from meerschaum.utils.typing import Callable, Any, Optional, Union, List, Dict,
|
|
11
11
|
from meerschaum.utils.packages import get_modules_from_package
|
12
12
|
_custom_actions = []
|
13
13
|
|
14
|
+
__all__ = (
|
15
|
+
'get_action',
|
16
|
+
'get_subactions',
|
17
|
+
'make_action',
|
18
|
+
'pre_sync_hook',
|
19
|
+
'post_sync_hook',
|
20
|
+
'get_main_action_name',
|
21
|
+
'get_completer',
|
22
|
+
)
|
23
|
+
|
14
24
|
def get_subactions(
|
15
25
|
action: Union[str, List[str]],
|
16
26
|
_actions: Optional[Dict[str, Callable[[Any], Any]]] = None,
|
@@ -101,9 +111,9 @@ def get_action(
|
|
101
111
|
|
102
112
|
|
103
113
|
def get_main_action_name(
|
104
|
-
|
105
|
-
|
106
|
-
|
114
|
+
action: Union[List[str], str],
|
115
|
+
_actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
|
116
|
+
) -> Union[str, None]:
|
107
117
|
"""
|
108
118
|
Given an action list, return the name of the main function.
|
109
119
|
For subactions, this will return the root function.
|
@@ -140,9 +150,9 @@ def get_main_action_name(
|
|
140
150
|
|
141
151
|
|
142
152
|
def get_completer(
|
143
|
-
|
144
|
-
|
145
|
-
|
153
|
+
action: Union[List[str], str],
|
154
|
+
_actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
|
155
|
+
) -> Union[
|
146
156
|
Callable[['meerschaum._internal.shell.Shell', str, str, int, int], List[str]], None
|
147
157
|
]:
|
148
158
|
"""Search for a custom completer function for an action."""
|
@@ -179,10 +189,10 @@ def get_completer(
|
|
179
189
|
|
180
190
|
|
181
191
|
def choose_subaction(
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
192
|
+
action: Optional[List[str]] = None,
|
193
|
+
options: Optional[Dict[str, Any]] = None,
|
194
|
+
**kw
|
195
|
+
) -> SuccessTuple:
|
186
196
|
"""
|
187
197
|
Given a dictionary of options and the standard Meerschaum actions list,
|
188
198
|
check if choice is valid and execute chosen function, else show available
|
@@ -247,7 +257,7 @@ def _get_subaction_names(action: str, globs: dict = None) -> List[str]:
|
|
247
257
|
return subactions
|
248
258
|
|
249
259
|
|
250
|
-
def choices_docstring(action: str, globs
|
260
|
+
def choices_docstring(action: str, globs: Optional[Dict[str, Any]] = None) -> str:
|
251
261
|
"""
|
252
262
|
Append the an action's available options to the module docstring.
|
253
263
|
This function is to be placed at the bottom of each action module.
|
meerschaum/actions/show.py
CHANGED
@@ -155,10 +155,10 @@ def _complete_show_config(action: Optional[List[str]] = None, **kw : Any):
|
|
155
155
|
|
156
156
|
|
157
157
|
def _show_pipes(
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
158
|
+
nopretty: bool = False,
|
159
|
+
debug: bool = False,
|
160
|
+
**kw: Any
|
161
|
+
) -> SuccessTuple:
|
162
162
|
"""
|
163
163
|
Print a stylized tree of available Meerschaum pipes.
|
164
164
|
Respects global ANSI and UNICODE settings.
|
@@ -170,7 +170,7 @@ def _show_pipes(
|
|
170
170
|
pipes = get_pipes(debug=debug, **kw)
|
171
171
|
|
172
172
|
if len(pipes) == 0:
|
173
|
-
return
|
173
|
+
return True, "No pipes to show."
|
174
174
|
|
175
175
|
if len(flatten_pipes_dict(pipes)) == 1:
|
176
176
|
return flatten_pipes_dict(pipes)[0].show(debug=debug, nopretty=nopretty, **kw)
|
meerschaum/actions/start.py
CHANGED
@@ -7,7 +7,7 @@ Start subsystems (API server, logging daemon, etc.).
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
-
from meerschaum.utils.typing import SuccessTuple, Optional, List, Any
|
10
|
+
from meerschaum.utils.typing import SuccessTuple, Optional, List, Any, Union
|
11
11
|
|
12
12
|
def start(
|
13
13
|
action: Optional[List[str]] = None,
|
@@ -23,6 +23,7 @@ def start(
|
|
23
23
|
'gui': _start_gui,
|
24
24
|
'webterm': _start_webterm,
|
25
25
|
'connectors': _start_connectors,
|
26
|
+
'pipeline': _start_pipeline,
|
26
27
|
}
|
27
28
|
return choose_subaction(action, options, **kw)
|
28
29
|
|
@@ -537,6 +538,75 @@ def _complete_start_connectors(**kw) -> List[str]:
|
|
537
538
|
return _complete_show_connectors(**kw)
|
538
539
|
|
539
540
|
|
541
|
+
def _start_pipeline(
|
542
|
+
action: Optional[List[str]] = None,
|
543
|
+
sub_args: Optional[List[str]] = None,
|
544
|
+
loop: bool = False,
|
545
|
+
min_seconds: Union[float, int, None] = 1.0,
|
546
|
+
params: Optional[Dict[str, Any]] = None,
|
547
|
+
**kwargs
|
548
|
+
) -> SuccessTuple:
|
549
|
+
"""
|
550
|
+
Run a series of Meerschaum commands as a single action.
|
551
|
+
|
552
|
+
Add `:` to the end of chained arguments to apply additional flags to the pipeline.
|
553
|
+
|
554
|
+
Examples
|
555
|
+
--------
|
556
|
+
|
557
|
+
`sync pipes -i sql:local + sync pipes -i sql:main :: -s 'daily'`
|
558
|
+
|
559
|
+
`show version + show arguments :: --loop`
|
560
|
+
|
561
|
+
"""
|
562
|
+
import time
|
563
|
+
from meerschaum._internal.entry import entry
|
564
|
+
from meerschaum.utils.warnings import info, warn
|
565
|
+
from meerschaum.utils.misc import is_int
|
566
|
+
|
567
|
+
do_n_times = (
|
568
|
+
int(action[0].lstrip('x'))
|
569
|
+
if action and is_int(action[0].lstrip('x'))
|
570
|
+
else 1
|
571
|
+
)
|
572
|
+
|
573
|
+
if not sub_args:
|
574
|
+
return False, "Nothing to do."
|
575
|
+
|
576
|
+
if min_seconds is None:
|
577
|
+
min_seconds = 1.0
|
578
|
+
|
579
|
+
ran_n_times = 0
|
580
|
+
success, msg = False, "Did not run pipeline."
|
581
|
+
def run_loop():
|
582
|
+
nonlocal ran_n_times, success, msg
|
583
|
+
while True:
|
584
|
+
success, msg = entry(sub_args, _patch_args=params)
|
585
|
+
ran_n_times += 1
|
586
|
+
|
587
|
+
if not loop and do_n_times == 1:
|
588
|
+
break
|
589
|
+
|
590
|
+
if min_seconds != 0 and ran_n_times != do_n_times:
|
591
|
+
info(f"Sleeping for {min_seconds} seconds...")
|
592
|
+
time.sleep(min_seconds)
|
593
|
+
|
594
|
+
if loop:
|
595
|
+
continue
|
596
|
+
|
597
|
+
if ran_n_times >= do_n_times:
|
598
|
+
break
|
599
|
+
|
600
|
+
try:
|
601
|
+
run_loop()
|
602
|
+
except KeyboardInterrupt:
|
603
|
+
warn("Cancelled pipeline.", stack=False)
|
604
|
+
|
605
|
+
if do_n_times != 1:
|
606
|
+
info(f"Ran pipeline {ran_n_times} time" + ('s' if ran_n_times != 1 else '') + '.')
|
607
|
+
return success, msg
|
608
|
+
|
609
|
+
|
540
610
|
### NOTE: This must be the final statement of the module.
|
541
611
|
### Any subactions added below these lines will not
|
542
612
|
### be added to the `help` docstring.
|
@@ -18,7 +18,7 @@ from fastapi import WebSocket, WebSocketDisconnect
|
|
18
18
|
from meerschaum.utils.misc import generate_password
|
19
19
|
from meerschaum.jobs import Job
|
20
20
|
from meerschaum.utils.warnings import warn
|
21
|
-
from meerschaum.utils.typing import SuccessTuple, Union, List, Dict
|
21
|
+
from meerschaum.utils.typing import SuccessTuple, Union, List, Dict, Any
|
22
22
|
from meerschaum.api import (
|
23
23
|
fastapi, app, endpoints, get_api_connector, debug, manager, private, no_auth
|
24
24
|
)
|
@@ -153,3 +153,50 @@ async def do_action_websocket(websocket: WebSocket):
|
|
153
153
|
job.delete()
|
154
154
|
_ = _temp_jobs.pop(job_name, None)
|
155
155
|
stop_event.set()
|
156
|
+
|
157
|
+
|
158
|
+
@app.post(actions_endpoint + "/{action}", tags=['Actions'])
|
159
|
+
def do_action_legacy(
|
160
|
+
action: str,
|
161
|
+
keywords: Dict[str, Any] = fastapi.Body(...),
|
162
|
+
curr_user = (
|
163
|
+
fastapi.Depends(manager) if not no_auth else None
|
164
|
+
),
|
165
|
+
) -> SuccessTuple:
|
166
|
+
"""
|
167
|
+
Perform a Meerschaum action (if permissions allow).
|
168
|
+
|
169
|
+
Parameters
|
170
|
+
----------
|
171
|
+
action: str
|
172
|
+
The action to perform.
|
173
|
+
|
174
|
+
keywords: Dict[str, Any]
|
175
|
+
The keywords dictionary to pass to the action.
|
176
|
+
|
177
|
+
Returns
|
178
|
+
-------
|
179
|
+
A `SuccessTuple`.
|
180
|
+
"""
|
181
|
+
if curr_user is not None and curr_user.type != 'admin':
|
182
|
+
from meerschaum.config import get_config
|
183
|
+
allow_non_admin = get_config(
|
184
|
+
'system', 'api', 'permissions', 'actions', 'non_admin', patch=True
|
185
|
+
)
|
186
|
+
if not allow_non_admin:
|
187
|
+
return False, (
|
188
|
+
"The administrator for this server has not allowed users to perform actions.\n\n"
|
189
|
+
+ "Please contact the system administrator, or if you are running this server, "
|
190
|
+
+ "open the configuration file with `edit config system` "
|
191
|
+
+ "and search for 'permissions'. "
|
192
|
+
+ "\nUnder the keys 'api:permissions:actions', "
|
193
|
+
+ "you can allow non-admin users to perform actions."
|
194
|
+
)
|
195
|
+
|
196
|
+
if action not in actions:
|
197
|
+
return False, f"Invalid action '{action}'."
|
198
|
+
|
199
|
+
keywords['mrsm_instance'] = keywords.get('mrsm_instance', str(get_api_connector()))
|
200
|
+
_debug = keywords.get('debug', debug)
|
201
|
+
keywords.pop('debug', None)
|
202
|
+
return actions[action](debug=_debug, **keywords)
|
meerschaum/config/_paths.py
CHANGED
@@ -185,6 +185,7 @@ paths = {
|
|
185
185
|
'SYSTEMD_RESOURCES_PATH' : ('{DOT_CONFIG_DIR_PATH}', 'systemd'),
|
186
186
|
'SYSTEMD_USER_RESOURCES_PATH' : ('{SYSTEMD_RESOURCES_PATH}', 'user'),
|
187
187
|
'SYSTEMD_ROOT_RESOURCES_PATH' : ('{ROOT_DIR_PATH}', 'systemd'),
|
188
|
+
'SYSTEMD_JOBS_RESOURCES_PATH' : ('{SYSTEMD_ROOT_RESOURCES_PATH}', 'services'),
|
188
189
|
'SYSTEMD_LOGS_RESOURCES_PATH' : ('{SYSTEMD_ROOT_RESOURCES_PATH}', 'logs'),
|
189
190
|
}
|
190
191
|
|
meerschaum/config/_version.py
CHANGED
@@ -33,7 +33,12 @@ class APIConnector(Connector):
|
|
33
33
|
delete,
|
34
34
|
wget,
|
35
35
|
)
|
36
|
-
from ._actions import
|
36
|
+
from ._actions import (
|
37
|
+
get_actions,
|
38
|
+
do_action,
|
39
|
+
do_action_async,
|
40
|
+
do_action_legacy,
|
41
|
+
)
|
37
42
|
from ._misc import get_mrsm_version, get_chaining_status
|
38
43
|
from ._pipes import (
|
39
44
|
register_pipe,
|
@@ -13,7 +13,7 @@ import asyncio
|
|
13
13
|
from functools import partial
|
14
14
|
|
15
15
|
import meerschaum as mrsm
|
16
|
-
from meerschaum.utils.typing import SuccessTuple, List, Callable
|
16
|
+
from meerschaum.utils.typing import SuccessTuple, List, Callable, Optional
|
17
17
|
from meerschaum.config.static import STATIC_CONFIG
|
18
18
|
|
19
19
|
ACTIONS_ENDPOINT: str = STATIC_CONFIG['api']['endpoints']['actions']
|
@@ -74,3 +74,79 @@ async def do_action_async(
|
|
74
74
|
break
|
75
75
|
|
76
76
|
return True, "Success"
|
77
|
+
|
78
|
+
|
79
|
+
def do_action_legacy(
|
80
|
+
self,
|
81
|
+
action: Optional[List[str]] = None,
|
82
|
+
sysargs: Optional[List[str]] = None,
|
83
|
+
debug: bool = False,
|
84
|
+
**kw
|
85
|
+
) -> SuccessTuple:
|
86
|
+
"""
|
87
|
+
NOTE: This method is deprecated.
|
88
|
+
Please use `do_action()` or `do_action_async()`.
|
89
|
+
|
90
|
+
Execute a Meerschaum action remotely.
|
91
|
+
|
92
|
+
If `sysargs` are provided, parse those instead.
|
93
|
+
Otherwise infer everything from keyword arguments.
|
94
|
+
|
95
|
+
Examples
|
96
|
+
--------
|
97
|
+
>>> conn = mrsm.get_connector('api:main')
|
98
|
+
>>> conn.do_action(['show', 'pipes'])
|
99
|
+
(True, "Success")
|
100
|
+
>>> conn.do_action(['show', 'arguments'], name='test')
|
101
|
+
(True, "Success")
|
102
|
+
"""
|
103
|
+
import sys, json
|
104
|
+
from meerschaum.utils.debug import dprint
|
105
|
+
from meerschaum.config.static import STATIC_CONFIG
|
106
|
+
from meerschaum.utils.misc import json_serialize_datetime
|
107
|
+
if action is None:
|
108
|
+
action = []
|
109
|
+
|
110
|
+
if sysargs is not None and action and action[0] == '':
|
111
|
+
from meerschaum._internal.arguments import parse_arguments
|
112
|
+
if debug:
|
113
|
+
dprint(f"Parsing sysargs:\n{sysargs}")
|
114
|
+
json_dict = parse_arguments(sysargs)
|
115
|
+
else:
|
116
|
+
json_dict = kw
|
117
|
+
json_dict['action'] = action
|
118
|
+
if 'noask' not in kw:
|
119
|
+
json_dict['noask'] = True
|
120
|
+
if 'yes' not in kw:
|
121
|
+
json_dict['yes'] = True
|
122
|
+
if debug:
|
123
|
+
json_dict['debug'] = debug
|
124
|
+
|
125
|
+
root_action = json_dict['action'][0]
|
126
|
+
del json_dict['action'][0]
|
127
|
+
r_url = f"{STATIC_CONFIG['api']['endpoints']['actions']}/{root_action}"
|
128
|
+
|
129
|
+
if debug:
|
130
|
+
from meerschaum.utils.formatting import pprint
|
131
|
+
dprint(f"Sending data to '{self.url + r_url}':")
|
132
|
+
pprint(json_dict, stream=sys.stderr)
|
133
|
+
|
134
|
+
response = self.post(
|
135
|
+
r_url,
|
136
|
+
data = json.dumps(json_dict, default=json_serialize_datetime),
|
137
|
+
debug = debug,
|
138
|
+
)
|
139
|
+
try:
|
140
|
+
response_list = json.loads(response.text)
|
141
|
+
if isinstance(response_list, dict) and 'detail' in response_list:
|
142
|
+
return False, response_list['detail']
|
143
|
+
except Exception as e:
|
144
|
+
print(f"Invalid response: {response}")
|
145
|
+
print(e)
|
146
|
+
return False, response.text
|
147
|
+
if debug:
|
148
|
+
dprint(response)
|
149
|
+
try:
|
150
|
+
return response_list[0], response_list[1]
|
151
|
+
except Exception as e:
|
152
|
+
return False, f"Failed to parse result from action '{root_action}'"
|