meerschaum 2.3.0.dev3__py3-none-any.whl → 2.3.0rc2__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 +3 -2
- meerschaum/__main__.py +0 -5
- meerschaum/_internal/arguments/__init__.py +1 -1
- meerschaum/_internal/arguments/_parse_arguments.py +56 -2
- meerschaum/_internal/arguments/_parser.py +6 -2
- meerschaum/_internal/entry.py +94 -23
- meerschaum/_internal/shell/Shell.py +112 -35
- meerschaum/actions/attach.py +12 -7
- meerschaum/actions/copy.py +68 -41
- meerschaum/actions/delete.py +75 -26
- meerschaum/actions/edit.py +3 -3
- meerschaum/actions/install.py +40 -32
- meerschaum/actions/pause.py +44 -27
- meerschaum/actions/restart.py +107 -0
- meerschaum/actions/show.py +8 -8
- meerschaum/actions/start.py +27 -46
- meerschaum/actions/stop.py +11 -4
- meerschaum/api/_events.py +10 -3
- meerschaum/api/dash/jobs.py +69 -70
- meerschaum/api/routes/_actions.py +8 -3
- meerschaum/api/routes/_jobs.py +37 -19
- meerschaum/config/_default.py +1 -1
- meerschaum/config/_paths.py +5 -0
- meerschaum/config/_version.py +1 -1
- meerschaum/config/static/__init__.py +5 -0
- meerschaum/connectors/Connector.py +13 -7
- meerschaum/connectors/__init__.py +21 -5
- meerschaum/connectors/api/APIConnector.py +3 -0
- meerschaum/connectors/api/_jobs.py +30 -3
- meerschaum/connectors/parse.py +10 -14
- meerschaum/core/Pipe/_bootstrap.py +16 -8
- meerschaum/jobs/_Executor.py +69 -0
- meerschaum/{utils/jobs → jobs}/_Job.py +169 -21
- meerschaum/jobs/_LocalExecutor.py +88 -0
- meerschaum/jobs/_SystemdExecutor.py +613 -0
- meerschaum/jobs/__init__.py +388 -0
- meerschaum/plugins/__init__.py +6 -6
- meerschaum/utils/daemon/Daemon.py +7 -0
- meerschaum/utils/daemon/RotatingFile.py +5 -2
- meerschaum/utils/daemon/StdinFile.py +12 -2
- meerschaum/utils/daemon/__init__.py +2 -0
- meerschaum/utils/formatting/_jobs.py +49 -25
- meerschaum/utils/misc.py +23 -5
- meerschaum/utils/packages/_packages.py +7 -4
- meerschaum/utils/process.py +9 -9
- meerschaum/utils/venv/__init__.py +2 -2
- {meerschaum-2.3.0.dev3.dist-info → meerschaum-2.3.0rc2.dist-info}/METADATA +14 -17
- {meerschaum-2.3.0.dev3.dist-info → meerschaum-2.3.0rc2.dist-info}/RECORD +54 -50
- meerschaum/utils/jobs/__init__.py +0 -245
- {meerschaum-2.3.0.dev3.dist-info → meerschaum-2.3.0rc2.dist-info}/LICENSE +0 -0
- {meerschaum-2.3.0.dev3.dist-info → meerschaum-2.3.0rc2.dist-info}/NOTICE +0 -0
- {meerschaum-2.3.0.dev3.dist-info → meerschaum-2.3.0rc2.dist-info}/WHEEL +0 -0
- {meerschaum-2.3.0.dev3.dist-info → meerschaum-2.3.0rc2.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.3.0.dev3.dist-info → meerschaum-2.3.0rc2.dist-info}/top_level.txt +0 -0
- {meerschaum-2.3.0.dev3.dist-info → meerschaum-2.3.0rc2.dist-info}/zip-safe +0 -0
meerschaum/actions/show.py
CHANGED
@@ -54,7 +54,7 @@ def _complete_show(
|
|
54
54
|
"""
|
55
55
|
Override the default Meerschaum `complete_` function.
|
56
56
|
"""
|
57
|
-
from meerschaum.actions.
|
57
|
+
from meerschaum.actions.delete import _complete_delete_jobs
|
58
58
|
|
59
59
|
if action is None:
|
60
60
|
action = []
|
@@ -65,10 +65,10 @@ def _complete_show(
|
|
65
65
|
'config' : _complete_show_config,
|
66
66
|
'package' : _complete_show_packages,
|
67
67
|
'packages' : _complete_show_packages,
|
68
|
-
'job' :
|
69
|
-
'jobs' :
|
70
|
-
'log' :
|
71
|
-
'logs' :
|
68
|
+
'job' : _complete_delete_jobs,
|
69
|
+
'jobs' : _complete_delete_jobs,
|
70
|
+
'log' : _complete_delete_jobs,
|
71
|
+
'logs' : _complete_delete_jobs,
|
72
72
|
}
|
73
73
|
|
74
74
|
if (
|
@@ -560,7 +560,7 @@ def _show_jobs(
|
|
560
560
|
"""
|
561
561
|
Show the currently running and stopped jobs.
|
562
562
|
"""
|
563
|
-
from meerschaum.
|
563
|
+
from meerschaum.jobs import get_filtered_jobs
|
564
564
|
from meerschaum.utils.formatting._jobs import pprint_jobs
|
565
565
|
|
566
566
|
jobs = get_filtered_jobs(executor_keys, action, debug=debug)
|
@@ -575,7 +575,7 @@ def _show_jobs(
|
|
575
575
|
" - start api -d\n" +
|
576
576
|
" - start job sync pipes --loop"
|
577
577
|
)
|
578
|
-
return
|
578
|
+
return True, "No jobs to show."
|
579
579
|
|
580
580
|
pprint_jobs(jobs, nopretty=nopretty)
|
581
581
|
return True, "Success"
|
@@ -602,7 +602,7 @@ def _show_logs(
|
|
602
602
|
from functools import partial
|
603
603
|
from datetime import datetime, timezone
|
604
604
|
from meerschaum.utils.packages import attempt_import, import_rich
|
605
|
-
from meerschaum.
|
605
|
+
from meerschaum.jobs import get_filtered_jobs, Job
|
606
606
|
from meerschaum.utils.warnings import warn, info
|
607
607
|
from meerschaum.utils.formatting import get_console, ANSI, UNICODE
|
608
608
|
from meerschaum.utils.misc import tail
|
meerschaum/actions/start.py
CHANGED
@@ -10,9 +10,9 @@ from __future__ import annotations
|
|
10
10
|
from meerschaum.utils.typing import SuccessTuple, Optional, List, Any
|
11
11
|
|
12
12
|
def start(
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
action: Optional[List[str]] = None,
|
14
|
+
**kw: Any,
|
15
|
+
) -> SuccessTuple:
|
16
16
|
"""
|
17
17
|
Start subsystems (API server, background job, etc.).
|
18
18
|
"""
|
@@ -28,16 +28,23 @@ def start(
|
|
28
28
|
|
29
29
|
|
30
30
|
def _complete_start(
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
action: Optional[List[str]] = None,
|
32
|
+
**kw: Any
|
33
|
+
) -> List[str]:
|
34
34
|
"""
|
35
35
|
Override the default Meerschaum `complete_` function.
|
36
36
|
"""
|
37
|
+
from meerschaum.actions.delete import _complete_delete_jobs
|
38
|
+
from functools import partial
|
37
39
|
|
38
40
|
if action is None:
|
39
41
|
action = []
|
40
42
|
|
43
|
+
_complete_start_jobs = partial(
|
44
|
+
_complete_delete_jobs,
|
45
|
+
_get_job_method=['stopped', 'paused'],
|
46
|
+
)
|
47
|
+
|
41
48
|
options = {
|
42
49
|
'job': _complete_start_jobs,
|
43
50
|
'jobs': _complete_start_jobs,
|
@@ -75,14 +82,15 @@ def _start_api(action: Optional[List[str]] = None, **kw):
|
|
75
82
|
from meerschaum.actions import actions
|
76
83
|
return actions['api'](action=['start'], **kw)
|
77
84
|
|
85
|
+
|
78
86
|
def _start_jobs(
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
87
|
+
action: Optional[List[str]] = None,
|
88
|
+
name: Optional[str] = None,
|
89
|
+
sysargs: Optional[List[str]] = None,
|
90
|
+
executor_keys: Optional[str] = None,
|
91
|
+
debug: bool = False,
|
92
|
+
**kw
|
93
|
+
) -> SuccessTuple:
|
86
94
|
"""
|
87
95
|
Run a Meerschaum action as a background job.
|
88
96
|
|
@@ -112,28 +120,24 @@ def _start_jobs(
|
|
112
120
|
Start the job 'happy_seal' but via the `--name` flag.
|
113
121
|
This only applies when no text follows the words 'start job'.
|
114
122
|
"""
|
115
|
-
import textwrap
|
116
123
|
from meerschaum.utils.warnings import warn, info
|
117
124
|
from meerschaum.utils.daemon._names import get_new_daemon_name
|
118
|
-
from meerschaum.
|
125
|
+
from meerschaum.jobs import (
|
119
126
|
Job,
|
120
|
-
get_jobs,
|
121
127
|
get_filtered_jobs,
|
122
128
|
get_stopped_jobs,
|
123
129
|
get_running_jobs,
|
124
130
|
get_paused_jobs,
|
125
|
-
|
131
|
+
_install_healthcheck_job,
|
126
132
|
)
|
127
|
-
from meerschaum._internal.arguments._parse_arguments import parse_arguments
|
128
133
|
from meerschaum.actions import actions
|
129
134
|
from meerschaum.utils.prompt import yes_no
|
130
135
|
from meerschaum.utils.formatting import print_tuple
|
131
|
-
from meerschaum.utils.formatting._jobs import
|
132
|
-
from meerschaum.utils.formatting._shell import clear_screen
|
136
|
+
from meerschaum.utils.formatting._jobs import pprint_jobs
|
133
137
|
from meerschaum.utils.misc import items_str
|
134
138
|
|
135
139
|
names = []
|
136
|
-
jobs = get_filtered_jobs(executor_keys, debug=debug)
|
140
|
+
jobs = get_filtered_jobs(executor_keys, action, debug=debug)
|
137
141
|
|
138
142
|
new_job = len(list(action)) > 0
|
139
143
|
_potential_jobs = {'known': [], 'unknown': []}
|
@@ -166,7 +170,7 @@ def _start_jobs(
|
|
166
170
|
+ items_str(_potential_jobs['unknown'])
|
167
171
|
+ " will be ignored."
|
168
172
|
),
|
169
|
-
stack
|
173
|
+
stack=False
|
170
174
|
)
|
171
175
|
|
172
176
|
### Determine the `names` list.
|
@@ -294,33 +298,10 @@ def _start_jobs(
|
|
294
298
|
+ ("Failed to start job" + ("s" if len(_failures) != 1 else '')
|
295
299
|
+ f" {items_str(_failures)}." if _failures else '')
|
296
300
|
)
|
301
|
+
_install_healthcheck_job()
|
297
302
|
return len(_failures) == 0, msg
|
298
303
|
|
299
304
|
|
300
|
-
def _complete_start_jobs(
|
301
|
-
action: Optional[List[str]] = None,
|
302
|
-
executor_keys: Optional[str] = None,
|
303
|
-
line: str = '',
|
304
|
-
**kw
|
305
|
-
) -> List[str]:
|
306
|
-
from meerschaum.utils.jobs import get_filtered_jobs
|
307
|
-
jobs = get_filtered_jobs(executor_keys, action)
|
308
|
-
if not action:
|
309
|
-
return list(jobs)
|
310
|
-
|
311
|
-
possibilities = []
|
312
|
-
_line_end = line.split(' ')[-1]
|
313
|
-
for name in jobs:
|
314
|
-
if name in action:
|
315
|
-
continue
|
316
|
-
if _line_end == '':
|
317
|
-
possibilities.append(name)
|
318
|
-
continue
|
319
|
-
if name.startswith(action[-1]):
|
320
|
-
possibilities.append(name)
|
321
|
-
return possibilities
|
322
|
-
|
323
|
-
|
324
305
|
def _start_gui(
|
325
306
|
action: Optional[List[str]] = None,
|
326
307
|
mrsm_instance: Optional[str] = None,
|
meerschaum/actions/stop.py
CHANGED
@@ -27,13 +27,20 @@ def _complete_stop(
|
|
27
27
|
"""
|
28
28
|
Override the default Meerschaum `complete_` function.
|
29
29
|
"""
|
30
|
-
from meerschaum.actions.
|
30
|
+
from meerschaum.actions.delete import _complete_delete_jobs
|
31
|
+
from functools import partial
|
32
|
+
|
31
33
|
if action is None:
|
32
34
|
action = []
|
33
35
|
|
36
|
+
_complete_stop_jobs = partial(
|
37
|
+
_complete_delete_jobs,
|
38
|
+
_get_job_method=('running', 'paused', 'restart'),
|
39
|
+
)
|
40
|
+
|
34
41
|
options = {
|
35
|
-
'job' :
|
36
|
-
'jobs' :
|
42
|
+
'job' : _complete_stop_jobs,
|
43
|
+
'jobs' : _complete_stop_jobs,
|
37
44
|
}
|
38
45
|
|
39
46
|
if (
|
@@ -64,7 +71,7 @@ def _stop_jobs(
|
|
64
71
|
|
65
72
|
To see running processes, run `show jobs`.
|
66
73
|
"""
|
67
|
-
from meerschaum.
|
74
|
+
from meerschaum.jobs import (
|
68
75
|
get_filtered_jobs,
|
69
76
|
get_running_jobs,
|
70
77
|
get_paused_jobs,
|
meerschaum/api/_events.py
CHANGED
@@ -19,7 +19,11 @@ from meerschaum.utils.debug import dprint
|
|
19
19
|
from meerschaum.connectors.poll import retry_connect
|
20
20
|
from meerschaum.utils.warnings import warn
|
21
21
|
from meerschaum._internal.term.tools import is_webterm_running
|
22
|
-
from meerschaum.
|
22
|
+
from meerschaum.jobs import (
|
23
|
+
start_check_jobs_thread,
|
24
|
+
stop_check_jobs_thread,
|
25
|
+
get_executor_keys_from_context,
|
26
|
+
)
|
23
27
|
|
24
28
|
_check_jobs_thread = None
|
25
29
|
|
@@ -47,7 +51,8 @@ async def startup():
|
|
47
51
|
await shutdown()
|
48
52
|
os._exit(1)
|
49
53
|
|
50
|
-
|
54
|
+
if get_executor_keys_from_context() == 'local':
|
55
|
+
start_check_jobs_thread()
|
51
56
|
|
52
57
|
|
53
58
|
@app.on_event("shutdown")
|
@@ -60,7 +65,9 @@ async def shutdown():
|
|
60
65
|
if get_api_connector().type == 'sql':
|
61
66
|
get_api_connector().engine.dispose()
|
62
67
|
|
63
|
-
|
68
|
+
if get_executor_keys_from_context() == 'local':
|
69
|
+
stop_check_jobs_thread()
|
70
|
+
|
64
71
|
from meerschaum.api.routes._actions import _temp_jobs
|
65
72
|
for name, job in _temp_jobs.items():
|
66
73
|
job.delete()
|
meerschaum/api/dash/jobs.py
CHANGED
@@ -16,13 +16,12 @@ from meerschaum.api import CHECK_UPDATE
|
|
16
16
|
dbc = attempt_import('dash_bootstrap_components', lazy=False, check_update=CHECK_UPDATE)
|
17
17
|
html, dcc = import_html(), import_dcc()
|
18
18
|
dateutil_parser = attempt_import('dateutil.parser', check_update=CHECK_UPDATE)
|
19
|
-
from meerschaum.
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
Daemon,
|
19
|
+
from meerschaum.jobs import (
|
20
|
+
get_jobs,
|
21
|
+
get_running_jobs,
|
22
|
+
get_paused_jobs,
|
23
|
+
get_stopped_jobs,
|
24
|
+
Job,
|
26
25
|
)
|
27
26
|
from meerschaum.config import get_config
|
28
27
|
from meerschaum.utils.misc import sorted_dict
|
@@ -38,27 +37,25 @@ def get_jobs_cards(state: WebState):
|
|
38
37
|
"""
|
39
38
|
Build cards and alerts lists for jobs.
|
40
39
|
"""
|
41
|
-
|
42
|
-
jobs = get_jobs()
|
40
|
+
jobs = get_jobs(include_hidden=False)
|
43
41
|
session_id = state['session-store.data'].get('session-id', None)
|
44
42
|
is_authenticated = is_session_authenticated(session_id)
|
45
43
|
|
46
|
-
alert = alert_from_success_tuple(daemons)
|
47
44
|
cards = []
|
48
45
|
|
49
46
|
for name, job in jobs.items():
|
50
47
|
d = job.daemon
|
51
48
|
footer_children = html.Div(
|
52
49
|
build_process_timestamps_children(d),
|
53
|
-
id = {'type': 'process-timestamps-div', 'index':
|
50
|
+
id = {'type': 'process-timestamps-div', 'index': name},
|
54
51
|
)
|
55
52
|
follow_logs_button = dbc.DropdownMenuItem(
|
56
53
|
"Follow logs",
|
57
|
-
id = {'type': 'follow-logs-button', 'index':
|
54
|
+
id = {'type': 'follow-logs-button', 'index': name},
|
58
55
|
)
|
59
56
|
download_logs_button = dbc.DropdownMenuItem(
|
60
57
|
"Download logs",
|
61
|
-
id = {'type': 'job-download-logs-button', 'index':
|
58
|
+
id = {'type': 'job-download-logs-button', 'index': name},
|
62
59
|
)
|
63
60
|
logs_menu_children = (
|
64
61
|
([follow_logs_button] if is_authenticated else []) + [download_logs_button]
|
@@ -66,19 +63,19 @@ def get_jobs_cards(state: WebState):
|
|
66
63
|
header_children = [
|
67
64
|
html.Div(
|
68
65
|
build_status_children(d),
|
69
|
-
id
|
70
|
-
style
|
66
|
+
id={'type': 'manage-job-status-div', 'index': name},
|
67
|
+
style={'float': 'left'},
|
71
68
|
),
|
72
69
|
html.Div(
|
73
70
|
dbc.DropdownMenu(
|
74
71
|
logs_menu_children,
|
75
|
-
label
|
76
|
-
size
|
77
|
-
align_end
|
78
|
-
color
|
79
|
-
menu_variant
|
72
|
+
label="Logs",
|
73
|
+
size="sm",
|
74
|
+
align_end=True,
|
75
|
+
color="secondary",
|
76
|
+
menu_variant='dark',
|
80
77
|
),
|
81
|
-
style
|
78
|
+
style={'float': 'right'},
|
82
79
|
),
|
83
80
|
]
|
84
81
|
|
@@ -87,10 +84,10 @@ def get_jobs_cards(state: WebState):
|
|
87
84
|
html.Div(
|
88
85
|
html.P(
|
89
86
|
d.label,
|
90
|
-
className
|
91
|
-
style
|
87
|
+
className="card-text job-card-text",
|
88
|
+
style={"word-wrap": "break-word"},
|
92
89
|
),
|
93
|
-
style
|
90
|
+
style={"white-space": "pre-wrap"},
|
94
91
|
),
|
95
92
|
html.Div(
|
96
93
|
(
|
@@ -98,9 +95,9 @@ def get_jobs_cards(state: WebState):
|
|
98
95
|
if is_authenticated
|
99
96
|
else []
|
100
97
|
),
|
101
|
-
id
|
98
|
+
id={'type': 'manage-job-buttons-div', 'index': name},
|
102
99
|
),
|
103
|
-
html.Div(id={'type': 'manage-job-alert-div', 'index':
|
100
|
+
html.Div(id={'type': 'manage-job-alert-div', 'index': name}),
|
104
101
|
]
|
105
102
|
|
106
103
|
cards.append(
|
@@ -114,11 +111,11 @@ def get_jobs_cards(state: WebState):
|
|
114
111
|
return cards, []
|
115
112
|
|
116
113
|
|
117
|
-
def build_manage_job_buttons_div_children(
|
114
|
+
def build_manage_job_buttons_div_children(job: Job):
|
118
115
|
"""
|
119
116
|
Return the children for the manage job buttons div.
|
120
117
|
"""
|
121
|
-
buttons = build_manage_job_buttons(
|
118
|
+
buttons = build_manage_job_buttons(job)
|
122
119
|
if not buttons:
|
123
120
|
return []
|
124
121
|
return [
|
@@ -130,96 +127,98 @@ def build_manage_job_buttons_div_children(daemon: Daemon):
|
|
130
127
|
]
|
131
128
|
|
132
129
|
|
133
|
-
def build_manage_job_buttons(
|
130
|
+
def build_manage_job_buttons(job: Job):
|
134
131
|
"""
|
135
|
-
Return the currently available job management buttons for a given
|
132
|
+
Return the currently available job management buttons for a given Job.
|
136
133
|
"""
|
137
|
-
if
|
134
|
+
if job is None:
|
138
135
|
return []
|
136
|
+
|
139
137
|
start_button = dbc.Button(
|
140
138
|
'Start',
|
141
|
-
size
|
142
|
-
color
|
143
|
-
style
|
144
|
-
id
|
139
|
+
size='sm',
|
140
|
+
color='success',
|
141
|
+
style={'width': '100%'},
|
142
|
+
id={
|
145
143
|
'type': 'manage-job-button',
|
146
144
|
'action': 'start',
|
147
|
-
'index':
|
145
|
+
'index': job.name,
|
148
146
|
},
|
149
147
|
)
|
150
148
|
pause_button = dbc.Button(
|
151
149
|
'Pause',
|
152
|
-
size
|
153
|
-
color
|
154
|
-
style
|
155
|
-
id
|
150
|
+
size='sm',
|
151
|
+
color='warning',
|
152
|
+
style={'width': '100%'},
|
153
|
+
id={
|
156
154
|
'type': 'manage-job-button',
|
157
155
|
'action': 'pause',
|
158
|
-
'index':
|
156
|
+
'index': job.name,
|
159
157
|
},
|
160
158
|
)
|
161
159
|
stop_button = dbc.Button(
|
162
160
|
'Stop',
|
163
|
-
size
|
164
|
-
color
|
165
|
-
style
|
166
|
-
id
|
161
|
+
size='sm',
|
162
|
+
color='danger',
|
163
|
+
style={'width': '100%'},
|
164
|
+
id={
|
167
165
|
'type': 'manage-job-button',
|
168
166
|
'action': 'stop',
|
169
|
-
'index':
|
167
|
+
'index': job.name,
|
170
168
|
},
|
171
169
|
)
|
172
170
|
delete_button = dbc.Button(
|
173
171
|
'Delete',
|
174
|
-
size
|
175
|
-
color
|
176
|
-
style
|
177
|
-
id
|
172
|
+
size='sm',
|
173
|
+
color='danger',
|
174
|
+
style={'width': '100%'},
|
175
|
+
id={
|
178
176
|
'type': 'manage-job-button',
|
179
177
|
'action': 'delete',
|
180
|
-
'index':
|
178
|
+
'index': job.name,
|
181
179
|
},
|
182
180
|
)
|
183
181
|
buttons = []
|
184
|
-
if
|
182
|
+
if job.status in ('stopped', 'paused'):
|
185
183
|
buttons.append(start_button)
|
186
|
-
if
|
184
|
+
if job.status == 'stopped':
|
187
185
|
buttons.append(delete_button)
|
188
|
-
if
|
186
|
+
if job.status in ('running',):
|
189
187
|
buttons.append(pause_button)
|
190
|
-
if
|
188
|
+
if job.status in ('running', 'paused'):
|
191
189
|
buttons.append(stop_button)
|
192
190
|
|
193
191
|
return buttons
|
194
192
|
|
195
193
|
|
196
|
-
def build_status_children(
|
194
|
+
def build_status_children(job: Job) -> List[html.P]:
|
197
195
|
"""
|
198
196
|
Return the status HTML component for this daemon.
|
199
197
|
"""
|
200
|
-
if
|
198
|
+
if job is None:
|
201
199
|
return STATUS_EMOJI['dne']
|
202
200
|
|
203
201
|
status_str = (
|
204
|
-
STATUS_EMOJI.get(
|
202
|
+
STATUS_EMOJI.get(job.status, STATUS_EMOJI['stopped'])
|
205
203
|
+ ' '
|
206
|
-
+
|
204
|
+
+ job.status.capitalize()
|
207
205
|
)
|
208
206
|
return html.P(
|
209
207
|
html.B(status_str),
|
210
|
-
className
|
208
|
+
className=f"{job.status}-job",
|
211
209
|
)
|
212
210
|
|
213
211
|
|
214
|
-
def build_process_timestamps_children(
|
212
|
+
def build_process_timestamps_children(job: Job) -> List[dbc.Row]:
|
215
213
|
"""
|
216
214
|
Return the children to the process timestamps in the footer of the job card.
|
217
215
|
"""
|
218
|
-
if
|
216
|
+
if job is None:
|
219
217
|
return []
|
218
|
+
|
220
219
|
children = []
|
221
220
|
for timestamp_key, timestamp_val in sorted_dict(
|
222
|
-
daemon.properties.get('process', {})
|
221
|
+
job.daemon.properties.get('process', {})
|
223
222
|
).items():
|
224
223
|
timestamp = dateutil_parser.parse(timestamp_val)
|
225
224
|
timestamp_str = timestamp.strftime('%Y-%m-%d %H:%M UTC')
|
@@ -229,21 +228,21 @@ def build_process_timestamps_children(daemon: Daemon) -> List[dbc.Row]:
|
|
229
228
|
dbc.Col(
|
230
229
|
html.P(
|
231
230
|
timestamp_key.capitalize(),
|
232
|
-
style
|
233
|
-
className
|
231
|
+
style={'font-size': 'small'},
|
232
|
+
className='text-muted mb-0',
|
234
233
|
),
|
235
|
-
width
|
234
|
+
width=4,
|
236
235
|
),
|
237
236
|
dbc.Col(
|
238
237
|
html.P(
|
239
238
|
timestamp_str,
|
240
|
-
style
|
241
|
-
className
|
239
|
+
style={'font-size': 'small', 'text-align': 'right'},
|
240
|
+
className='text-muted mb-0',
|
242
241
|
),
|
243
|
-
width
|
242
|
+
width=8,
|
244
243
|
),
|
245
244
|
],
|
246
|
-
justify
|
245
|
+
justify='between',
|
247
246
|
)
|
248
247
|
)
|
249
248
|
return children
|
@@ -16,7 +16,7 @@ from datetime import datetime, timezone
|
|
16
16
|
from fastapi import WebSocket, WebSocketDisconnect
|
17
17
|
|
18
18
|
from meerschaum.utils.misc import generate_password
|
19
|
-
from meerschaum.
|
19
|
+
from meerschaum.jobs import Job
|
20
20
|
from meerschaum.utils.warnings import warn
|
21
21
|
from meerschaum.utils.typing import SuccessTuple, Union, List, Dict
|
22
22
|
from meerschaum.api import (
|
@@ -92,6 +92,7 @@ async def do_action_websocket(websocket: WebSocket):
|
|
92
92
|
)
|
93
93
|
|
94
94
|
job = None
|
95
|
+
job_name = '.' + generate_password(12)
|
95
96
|
try:
|
96
97
|
token = await websocket.receive_text()
|
97
98
|
user = await manager.get_current_user(token) if not no_auth else None
|
@@ -101,7 +102,11 @@ async def do_action_websocket(websocket: WebSocket):
|
|
101
102
|
detail="Invalid credentials.",
|
102
103
|
)
|
103
104
|
|
104
|
-
auth_success, auth_msg =
|
105
|
+
auth_success, auth_msg = (
|
106
|
+
is_user_allowed_to_execute(user)
|
107
|
+
if not no_auth
|
108
|
+
else (True, "Success")
|
109
|
+
)
|
105
110
|
auth_payload = {
|
106
111
|
'is_authenticated': auth_success,
|
107
112
|
'timestamp': datetime.now(timezone.utc).isoformat(),
|
@@ -116,10 +121,10 @@ async def do_action_websocket(websocket: WebSocket):
|
|
116
121
|
_ = kwargs.pop('shell', None)
|
117
122
|
sysargs = parse_dict_to_sysargs(kwargs)
|
118
123
|
|
119
|
-
job_name = '.' + generate_password(12)
|
120
124
|
job = Job(
|
121
125
|
job_name,
|
122
126
|
sysargs,
|
127
|
+
executor_keys='local',
|
123
128
|
_properties={
|
124
129
|
'logs': {
|
125
130
|
'write_timestamps': False,
|