automagix 4.0.0__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.
- automagix-4.0.0/LICENSE +22 -0
- automagix-4.0.0/PKG-INFO +639 -0
- automagix-4.0.0/README.md +610 -0
- automagix-4.0.0/automagix/__init__.py +91 -0
- automagix-4.0.0/automagix/automagix.py +185 -0
- automagix-4.0.0/automagix/automagix_test.py +34 -0
- automagix-4.0.0/automagix/batch_runner.py +70 -0
- automagix-4.0.0/automagix/bundlewrap.py +75 -0
- automagix-4.0.0/automagix/colors.py +42 -0
- automagix-4.0.0/automagix/command.py +600 -0
- automagix-4.0.0/automagix/command_test.py +169 -0
- automagix-4.0.0/automagix/config.py +412 -0
- automagix-4.0.0/automagix/config_test.py +95 -0
- automagix-4.0.0/automagix/environment.py +113 -0
- automagix-4.0.0/automagix/environment_test.py +34 -0
- automagix-4.0.0/automagix/helpers.py +103 -0
- automagix-4.0.0/automagix/logger.py +95 -0
- automagix-4.0.0/automagix/parallel.py +194 -0
- automagix-4.0.0/automagix/parallel_runner.py +124 -0
- automagix-4.0.0/automagix/parallel_ui.py +222 -0
- automagix-4.0.0/automagix/progress_bar.py +285 -0
- automagix-4.0.0/automagix/shell_completion.py +64 -0
- automagix-4.0.0/automagix.egg-info/PKG-INFO +639 -0
- automagix-4.0.0/automagix.egg-info/SOURCES.txt +29 -0
- automagix-4.0.0/automagix.egg-info/dependency_links.txt +1 -0
- automagix-4.0.0/automagix.egg-info/entry_points.txt +4 -0
- automagix-4.0.0/automagix.egg-info/requires.txt +19 -0
- automagix-4.0.0/automagix.egg-info/top_level.txt +1 -0
- automagix-4.0.0/pyproject.toml +37 -0
- automagix-4.0.0/setup.cfg +4 -0
- automagix-4.0.0/tests/test_environment.py +72 -0
automagix-4.0.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019-2026 //SEIBERT/MEDIA GmbH
|
|
4
|
+
Copyright (c) 2019-2026 Johannes Paul
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
automagix-4.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: automagix
|
|
3
|
+
Version: 4.0.0
|
|
4
|
+
Summary: Automation wrapper for bash and python commands
|
|
5
|
+
Author-email: Johannes Paul <vanadinit@quantentunnel.de>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://codeberg.org/vanadinit/automagix
|
|
8
|
+
Keywords: bash,shell,command,automation,process,wrapper,devops,system administration
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: pyyaml>=5.1
|
|
15
|
+
Provides-Extra: tests
|
|
16
|
+
Requires-Dist: cython<3.0.0; extra == "tests"
|
|
17
|
+
Requires-Dist: pytest; extra == "tests"
|
|
18
|
+
Requires-Dist: pytest-docker; extra == "tests"
|
|
19
|
+
Requires-Dist: flake8; extra == "tests"
|
|
20
|
+
Provides-Extra: shell-completion
|
|
21
|
+
Requires-Dist: argcomplete; extra == "shell-completion"
|
|
22
|
+
Provides-Extra: progress-bar
|
|
23
|
+
Requires-Dist: tqdm>=4.66.0; extra == "progress-bar"
|
|
24
|
+
Provides-Extra: bundlewrap
|
|
25
|
+
Requires-Dist: bundlewrap; extra == "bundlewrap"
|
|
26
|
+
Provides-Extra: teamvault
|
|
27
|
+
Requires-Dist: bundlewrap-teamvault; extra == "teamvault"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# automagix
|
|
31
|
+
Automation wrapper for bash and python commands. Extended Features version.
|
|
32
|
+
Fork of Automatix (https://github.com/seibert-media/automatix)
|
|
33
|
+
|
|
34
|
+
# DESCRIPTION
|
|
35
|
+
|
|
36
|
+
**automagix** is a wrapper for scripted sysadmin tasks. It offers
|
|
37
|
+
some useful functionality for easier scripting and having full
|
|
38
|
+
control over the automated process.
|
|
39
|
+
|
|
40
|
+
The idea of **automagix** is to write down all the commands you would
|
|
41
|
+
normally type to your commandline or python console into a YAML file.
|
|
42
|
+
Then use **automagix** to execute these commands.
|
|
43
|
+
|
|
44
|
+
There are different modes for **automagix** to work. Without any
|
|
45
|
+
parameters automagix will try to execute the specified command
|
|
46
|
+
pipeline from the script file until an error occurs or the pipeline
|
|
47
|
+
is done. The interactive mode (**-i**) asks for every single
|
|
48
|
+
commandline step whether to execute, skip or abort.
|
|
49
|
+
Forced mode (**-f**) will also proceed if errors occur.
|
|
50
|
+
|
|
51
|
+
**automagix** was originally designed for internal Seibert Group use.
|
|
52
|
+
It comes therefore with bundlewrap and teamvault support as well as
|
|
53
|
+
the possibility to use your own logging library.
|
|
54
|
+
|
|
55
|
+
## Warning:
|
|
56
|
+
|
|
57
|
+
Beware that this tool cannot substitute the system administrators
|
|
58
|
+
brain and it needs a responsible handling, since you can do
|
|
59
|
+
(and destroy) almost everything with it.
|
|
60
|
+
|
|
61
|
+
**Automagix** evaluates YAML files and executes defined commands as
|
|
62
|
+
shell or python commands. There is no check for harmful commands.
|
|
63
|
+
Be aware that this can cause critical damage to your system.
|
|
64
|
+
|
|
65
|
+
Please use the interactive mode and doublecheck commands before
|
|
66
|
+
executing. Usage of automagix is at your own risk!
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# INSTALLATION
|
|
70
|
+
|
|
71
|
+
Automagix requires Python ≥ 3.10.
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
pip install automagix
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
# CONFIGURATION
|
|
78
|
+
|
|
79
|
+
You can specify a path to a configuration YAML file via the
|
|
80
|
+
environment variable **AUTOMAGIX_CONFIG**.
|
|
81
|
+
Default location is "~/.automagix.cfg.yaml".
|
|
82
|
+
All (string) configuration values can be overwritten by the
|
|
83
|
+
corresponding upper case environment variables preceeded
|
|
84
|
+
by 'AUTOMAGIX_', e.g. _AUTOMAGIX_ENCODING_.
|
|
85
|
+
|
|
86
|
+
### Example: .automagix.cfg.yaml
|
|
87
|
+
|
|
88
|
+
# Path to scripts directory
|
|
89
|
+
script_dir: '~/automagix_script_files'
|
|
90
|
+
|
|
91
|
+
# Global constants for use in pipeline scripts
|
|
92
|
+
constants:
|
|
93
|
+
apt_update: 'apt-get -qy update'
|
|
94
|
+
apt_upgrade: 'DEBIAN_FRONTEND=noninteractive apt-get -qy -o Dpkg::Options::=--force-confold --no-install-recommends upgrade'
|
|
95
|
+
apt_full_upgrade: 'DEBIAN_FRONTEND=noninteractive apt-get -qy -o Dpkg::Options::=--force-confold --no-install-recommends full-upgrade'
|
|
96
|
+
|
|
97
|
+
# Encoding
|
|
98
|
+
encoding: 'utf-8'
|
|
99
|
+
|
|
100
|
+
# Path to local bash (default: /bin/bash)
|
|
101
|
+
bash_path: '/bin/bash'
|
|
102
|
+
|
|
103
|
+
# SSH Command used for remote connections
|
|
104
|
+
# You propably want -t for pseudo-terminal allocation here.
|
|
105
|
+
ssh_cmd: 'ssh -t {hostname} sudo '
|
|
106
|
+
|
|
107
|
+
# Logger
|
|
108
|
+
logger: 'mylogger'
|
|
109
|
+
|
|
110
|
+
# Logging library (has to implement the init_logger method)
|
|
111
|
+
logging_lib: 'mylib.logging'
|
|
112
|
+
|
|
113
|
+
# Logfile directory for parallel processing (ONLY for parallel processing!)
|
|
114
|
+
logfile_dir: 'automagix_logs'
|
|
115
|
+
|
|
116
|
+
# Enable support for modules: bundlewrap, teamvault.
|
|
117
|
+
modules: ['bundlewrap', 'teamvault']
|
|
118
|
+
|
|
119
|
+
# Activate progress bar: "Basic" or "Tqdm", default "" (no progress bar)
|
|
120
|
+
progress_bar: Basic
|
|
121
|
+
|
|
122
|
+
# Startup script, which is triggered on every start of Automagix.
|
|
123
|
+
# The whole Automagix call with all arguments is passed through as arguments.
|
|
124
|
+
startup_script: '/some/path/bin/automagix_startup.sh'
|
|
125
|
+
|
|
126
|
+
# SYNOPSIS
|
|
127
|
+
|
|
128
|
+
**automagix**
|
|
129
|
+
\[**--help**|**-h**\]
|
|
130
|
+
\[**--systems** \[_SYSTEM1=ADDRESS_OR_NODENAME_ ...\]\]
|
|
131
|
+
\[**--vars** \[_VAR1=VALUE1_ ...\]\]
|
|
132
|
+
\[**--secrets** \[_SECRET1=SECRETID_ ...\]\]
|
|
133
|
+
\[**--vars-file** _VARS_FILE_PATH_ \]
|
|
134
|
+
\[**--print-overview**|**-p**\]
|
|
135
|
+
\[**--jump-to**|**-j** _JUMP_TO_\]
|
|
136
|
+
\[**--steps**|**-s** _STEPS_\]
|
|
137
|
+
\[**--interactive**|**-i**\]
|
|
138
|
+
\[**--force**|**-f**\]
|
|
139
|
+
\[**--debug**|**-d**\]
|
|
140
|
+
\[**--**\] **scriptfile**
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
## OPTIONS
|
|
144
|
+
|
|
145
|
+
**scriptfile**
|
|
146
|
+
: The only required parameter for this tool to work. Use " -- " if
|
|
147
|
+
needed to delimit this from argument fields. See **SCRIPTFILE**
|
|
148
|
+
section for more information.
|
|
149
|
+
|
|
150
|
+
**-h**, **--help**
|
|
151
|
+
: View help message and exit.
|
|
152
|
+
|
|
153
|
+
**--systems** _SYSTEM1=ADDRESS_OR_NODENAME_
|
|
154
|
+
: Use this to set systems without adding them to the
|
|
155
|
+
scriptfile or to overwrite them. You can specify multiple
|
|
156
|
+
systems like: --systems v1=string1 v2=string2 v3=string3
|
|
157
|
+
|
|
158
|
+
**--vars** _VAR1=VALUE1_
|
|
159
|
+
: Use this to set vars without adding them to the scriptfile
|
|
160
|
+
or to overwrite them. You can specify multiple vars
|
|
161
|
+
like: --vars v1=string1 v2=string2 v3=string3
|
|
162
|
+
|
|
163
|
+
**--secrets** _SECRET1=SECRETID_
|
|
164
|
+
: Use this to set secrets without adding them to the
|
|
165
|
+
scriptfile or to overwrite them. You can specify multiple
|
|
166
|
+
secrets like: --secrets v1=string1 v2=string2 v3=string3 *(only if
|
|
167
|
+
teamvault is enabled)*
|
|
168
|
+
|
|
169
|
+
**--vars-file** _VARS_FILE_PATH_
|
|
170
|
+
: Use this to specify a CSV file from where **automagix** reads
|
|
171
|
+
systems, variables and secrets. First row must contain the field
|
|
172
|
+
types and names. You may also specify an `label` and `group` field.
|
|
173
|
+
|
|
174
|
+
The `label` field can be to achieve a better overview and which row
|
|
175
|
+
is currently executed. It is used, when printing error messages or
|
|
176
|
+
as status line in screens for parallel processing. Without label
|
|
177
|
+
the row number is displayed.
|
|
178
|
+
|
|
179
|
+
The `group` field is only relevant for parallel processing. Row of
|
|
180
|
+
the same group are grouped together in a single screen and processed
|
|
181
|
+
sequentially there. Different groups are processed parallel.
|
|
182
|
+
Rows without specified group are run each in a parallel screen.
|
|
183
|
+
These rows are processed after the groups.
|
|
184
|
+
|
|
185
|
+
Example header: `label,group,systems:mysystem,vars:myvar`.
|
|
186
|
+
|
|
187
|
+
**--parallel**
|
|
188
|
+
: Run CSV file entries parallel in screen sessions; only valid with --vars-file.
|
|
189
|
+
GNU screen has to be installed. See EXTRAS section below.
|
|
190
|
+
|
|
191
|
+
**--print-overview**, **-p**
|
|
192
|
+
: Just print command pipeline overview with indices then exit without
|
|
193
|
+
executing the commandline. Note that the *always pipeline* will be
|
|
194
|
+
executed anyway.
|
|
195
|
+
|
|
196
|
+
**--jump-to** _JUMP_TO_, **-j** _JUMP_TO_
|
|
197
|
+
: Jump to step with index _JUMP_TO_ instead of starting at the
|
|
198
|
+
beginning. Use this option without argument to get an interactive selection.
|
|
199
|
+
You can also use negative numbers to start counting from the end.
|
|
200
|
+
|
|
201
|
+
**--steps** _STEPS_, **-s** _STEPS_
|
|
202
|
+
: Only execute these steps (comma-separated indices) or exclude steps
|
|
203
|
+
by prepending the comma-separated list with "e".
|
|
204
|
+
Examples: `-s 1,3,7`, `-s e2`, `-s e0,5,7,2`
|
|
205
|
+
|
|
206
|
+
**--interactive**, **-i**
|
|
207
|
+
: Confirm actions before executing.
|
|
208
|
+
|
|
209
|
+
**--force**, **-f**
|
|
210
|
+
: Try always to proceed (except manual steps), even if errors occur
|
|
211
|
+
(no retries).
|
|
212
|
+
|
|
213
|
+
**--debug**, **-d**
|
|
214
|
+
: Activate debug log level.
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
### EXAMPLE: Usage
|
|
218
|
+
|
|
219
|
+
automagix -i --systems source=sourcesystem.com target=targetsystem.org -- scriptfile.yaml
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
## SCRIPTFILE
|
|
223
|
+
|
|
224
|
+
The **scriptfile** describes your automated process. Therefore it
|
|
225
|
+
contains information about systems, variables, secrets and the
|
|
226
|
+
command pipeline.
|
|
227
|
+
|
|
228
|
+
You can provide a path to your **scriptfile** or place your
|
|
229
|
+
scriptfile in the predefined directory (see **CONFIGURATION**
|
|
230
|
+
section, _script_dir_). The path has precedence over the predefined
|
|
231
|
+
directory, if the file exists at both locations.
|
|
232
|
+
|
|
233
|
+
The **scriptfile** has to contain valid YAML.
|
|
234
|
+
|
|
235
|
+
### EXAMPLE: scriptfile
|
|
236
|
+
|
|
237
|
+
name: Migration Server XY
|
|
238
|
+
# Systems you like to refer to in pipeline (accessible via 'SYSTEMS.source')
|
|
239
|
+
# If Bundlewrap support is activated use node names instead of hostnames or add preceeding 'hostname!'.
|
|
240
|
+
require_version: '1.5.0'
|
|
241
|
+
systems:
|
|
242
|
+
source: sourcesystem.com
|
|
243
|
+
target: targetsystem.org
|
|
244
|
+
# Custom vars to use in pipeline
|
|
245
|
+
vars:
|
|
246
|
+
version: 1.2.3
|
|
247
|
+
domain: 'bla.mein-test-system'
|
|
248
|
+
# Teamvault Secrets, if activated (left: like vars, right: SECRETID_FIELD, FIELD=username|password|file)
|
|
249
|
+
secrets:
|
|
250
|
+
web_user: v6GQag_username
|
|
251
|
+
web_pw: v6GQag_password
|
|
252
|
+
# Precommands, which are executed before each shell command in the main pipeline
|
|
253
|
+
precommands:
|
|
254
|
+
local: '. myfunctions'
|
|
255
|
+
remote: '. /tmp/myfunctions'
|
|
256
|
+
# like command pipeline but will be exectuted always beforehand
|
|
257
|
+
always:
|
|
258
|
+
- python: |
|
|
259
|
+
import mylib as nc
|
|
260
|
+
PERSISTENT_VARS.update(locals())
|
|
261
|
+
pipeline:
|
|
262
|
+
- remote@target: systemctl stop server
|
|
263
|
+
- remote@source: zfs snapshot -r tank@before-migration
|
|
264
|
+
- manual: Please trigger preparing tasks via webinterface
|
|
265
|
+
- myvar=local: curl -L -vvv -k https://{domain}/
|
|
266
|
+
- local: echo "1.1.1.1 {domain}" >> /etc/hosts
|
|
267
|
+
- sla=python: NODES.source.metadata.get('sla')
|
|
268
|
+
- python: |
|
|
269
|
+
sla = '{sla}'
|
|
270
|
+
if sla == 'gold':
|
|
271
|
+
print('Wow that\'s pretty cool. You have SLA Gold.')
|
|
272
|
+
else:
|
|
273
|
+
print('Oh. Running out of money? SLA Gold is worth it. You should check your wallet.')
|
|
274
|
+
PERSISTENT_VARS['sla'] = sla
|
|
275
|
+
- cond=python: sla == 'gold'
|
|
276
|
+
- cond?local: echo "This command is only executed if sla is gold."
|
|
277
|
+
cleanup:
|
|
278
|
+
- local: rm temp_files
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
### FIELDS
|
|
282
|
+
|
|
283
|
+
**name** _(string)_
|
|
284
|
+
: Just a name for the process. Does not do anything.
|
|
285
|
+
|
|
286
|
+
**require_version** _(string)_
|
|
287
|
+
: The required Automagix version for this script to run. Similar to the
|
|
288
|
+
[Python version specifiers](https://packaging.python.org/en/latest/specifications/version-specifiers/#version-specifiers).
|
|
289
|
+
Multiple conditions can be separated by comma. Allowed operators are: "==","!=",">=" (default),"<=",">","<","~="
|
|
290
|
+
|
|
291
|
+
**systems** _(associative array)_
|
|
292
|
+
: Define some systems. Value has to be a valid SSH destination like an
|
|
293
|
+
IP address or hostname. If Bundlewrap support is enabled, it has to
|
|
294
|
+
be a valid and existing Bundlewrap node or group name, or you can
|
|
295
|
+
precede your IP or hostname with `hostname!` to define a
|
|
296
|
+
non-Bundlewrap system.
|
|
297
|
+
You can refer to these systems in the command pipeline in multiple ways:
|
|
298
|
+
|
|
299
|
+
1) remote@systemname as your command action (see below)
|
|
300
|
+
|
|
301
|
+
2) via {SYSTEMS.systemname} which will be replaced with the value
|
|
302
|
+
|
|
303
|
+
3) via SYSTEMS.systemname in python actions which contains the value
|
|
304
|
+
|
|
305
|
+
4) via NODES.systemname in python actions to use the Bundlewrap node
|
|
306
|
+
object (Bundlewrap nodes only, no groups)
|
|
307
|
+
|
|
308
|
+
**vars** _(associative array)_
|
|
309
|
+
: Define some vars. Note: Only valid Python variable names are allowed.
|
|
310
|
+
To specify a variable type use `type|varname` where *type* is
|
|
311
|
+
one of *int, float, bool, str* and varname the variable name.
|
|
312
|
+
Automatix will try to convert an assigned value to the specified type.
|
|
313
|
+
**Note**: For the boolean type the string "False" and upper/lower-case
|
|
314
|
+
variations are converted to `False` deviating from Python's normal behavior.
|
|
315
|
+
Variables are accessible in the command pipeline via
|
|
316
|
+
{varname} (converted to *str*) and in python actions via `VARS.varname`.
|
|
317
|
+
|
|
318
|
+
**secrets** _(associative array)_
|
|
319
|
+
: Define teamvault secrets. Value has to be in this format:
|
|
320
|
+
_SECRETID_FIELD_. _FIELD_ must be one of username, password or file.
|
|
321
|
+
The resolved secret values are accessible in command line via
|
|
322
|
+
{secretname}. *(only if teamvault is enabled)*
|
|
323
|
+
|
|
324
|
+
**precommands** _(associative array)_
|
|
325
|
+
: Define a command which is executed before every shell command.
|
|
326
|
+
You can specify a command for local and remote commands separately.
|
|
327
|
+
This can be useful to source files with shell functions you want to use.
|
|
328
|
+
|
|
329
|
+
**always**, **cleanup** _(list of associative arrays)_
|
|
330
|
+
: See **ALWAYS / CLEANUP PIPELINE** section.
|
|
331
|
+
|
|
332
|
+
**pipeline** _(list of associative arrays)_
|
|
333
|
+
: See **PIPELINE** section.
|
|
334
|
+
|
|
335
|
+
### PIPELINE
|
|
336
|
+
|
|
337
|
+
Here you define the commands automagix shall execute.
|
|
338
|
+
|
|
339
|
+
**KEY**: One of these possible command actions:
|
|
340
|
+
|
|
341
|
+
1) **manual**: Some manual instruction for the user. The user has to
|
|
342
|
+
confirm, that automagix may proceed.
|
|
343
|
+
|
|
344
|
+
2) **local**: Local shell command to execute. The Bash specified
|
|
345
|
+
in `bash_path` (default: /bin/bash) will be used for execution.
|
|
346
|
+
The environment is inherited with additional
|
|
347
|
+
**RUNNING_INSIDE_AUTOMAGIX** set to 1.
|
|
348
|
+
|
|
349
|
+
3) **remote@systemname**: Remote shell command to execute. Systemname
|
|
350
|
+
has to be a defined system. The command will be run via SSH (without
|
|
351
|
+
pseudo-terminal allocation). It uses the standard SSH command.
|
|
352
|
+
Therefore your .ssh/config should be respected.
|
|
353
|
+
If systemname is a Bundlewrap group, the remote command will be
|
|
354
|
+
executed sequentially for every node.
|
|
355
|
+
|
|
356
|
+
4) **python**: Python code to execute.
|
|
357
|
+
* `PERSISTENT_VARS`, `PVARS`, `SkipBatchItemException`, `AbortException`
|
|
358
|
+
are available, see corresponding sections in **TIPS & TRICKS**
|
|
359
|
+
* Notice that the variable `VARS` contains
|
|
360
|
+
the Automagix variables as a dictionary. `VARS` supports also
|
|
361
|
+
the attribute notation like `VARS.myvariable`. You can use it
|
|
362
|
+
to access or change the variables directly.
|
|
363
|
+
* The path to the executed script file is available as `SCRIPT_FILE_PATH`.
|
|
364
|
+
* You can refer to systems and constants via `SYSTEMS.systemname`
|
|
365
|
+
and `CONST.constantname`.
|
|
366
|
+
* If bundlewrap is enabled, the Bundlewrap repository object is
|
|
367
|
+
available via `AUTOMAGIX_BW_REPO` and system node objects are
|
|
368
|
+
available via `NODES.systemname` (replace "systemname").
|
|
369
|
+
Use `AUTOMAGIX_BW_REPO.reload()` to reinitialize the Bundlewrap
|
|
370
|
+
repository from the file system. This can be useful for using
|
|
371
|
+
newly created nodes (e.g. remote commands).
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
**ASSIGNMENT**: For **local**, **remote** and **python** action you
|
|
375
|
+
can also define a variable to which the output will be assigned.
|
|
376
|
+
To do this prefix the desired variablename and = before the action
|
|
377
|
+
key, e.g. `myvar=python: NODES.system.hostname`. Be careful when
|
|
378
|
+
working with multiline statements. In **python** the first line is
|
|
379
|
+
likely to set the variable.
|
|
380
|
+
Only for **local** and **remote** action: If a variable type was
|
|
381
|
+
specified in the **vars** section, Automatix will also try to
|
|
382
|
+
convert the value here.
|
|
383
|
+
|
|
384
|
+
**CONDITIONS**: You can define the command only to be executed if
|
|
385
|
+
your condition variable evaluates to "True" in Python. To achieve
|
|
386
|
+
this write the variable name followed by a question mark at the very
|
|
387
|
+
beginning like `cond?python: destroy_system()`. Be aware that all
|
|
388
|
+
output from **local** or **remote** commands will lead to a non-empty
|
|
389
|
+
string which evaluates to "True" in Python, but empty output will
|
|
390
|
+
evaluate to "False". Use `!?` instead of `?` to invert the condition.
|
|
391
|
+
|
|
392
|
+
**STATIC_FLAG**: If you do not want values to be replaced in your command,
|
|
393
|
+
you can suffix the command key with '-' to indicate a static command
|
|
394
|
+
value, e.g. `python-: f'{this} is not replaced'`. This is especially
|
|
395
|
+
useful for Python commands which use curly brackets themselves.
|
|
396
|
+
|
|
397
|
+
**VALUE**: Your command. Variables will be replaced with Python
|
|
398
|
+
format function. Therefore, use curly brackets to refer to variables,
|
|
399
|
+
systems, secrets and constants.
|
|
400
|
+
|
|
401
|
+
Constants are available via CONST.KEY, where KEY is the key of your
|
|
402
|
+
constants in your **CONFIGURATION** file. There you can define some
|
|
403
|
+
widely used constants.
|
|
404
|
+
|
|
405
|
+
In most cases its a good idea to define your command in quotes to
|
|
406
|
+
avoid parsing errors, but it is not always necessary. Another way is
|
|
407
|
+
to use '|' to indicate a _literal scalar block_. There you can even
|
|
408
|
+
define whole program structures for python (see example).
|
|
409
|
+
|
|
410
|
+
#### Escaping in Pipeline
|
|
411
|
+
|
|
412
|
+
Because automagix uses Python's format() function (not for static commands):
|
|
413
|
+
`{` -> `{{`
|
|
414
|
+
`}` -> `}}`
|
|
415
|
+
|
|
416
|
+
Standard YAML escapes (see also https://yaml.org/spec/1.2/spec.html):
|
|
417
|
+
`'` -> `''`
|
|
418
|
+
`"` -> `\"`
|
|
419
|
+
`\ ` -> `\\`
|
|
420
|
+
`:` -> Please use quotes (double or single).
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
### ALWAYS / CLEANUP PIPELINE
|
|
424
|
+
|
|
425
|
+
Same usage as the 'normal' command pipeline, but will be executed
|
|
426
|
+
every time at start of automagix (**always**) or at the end
|
|
427
|
+
(**cleanup**) even if aborted (a). The commands are executed without
|
|
428
|
+
--interactive flag, independend of the specified parameters.
|
|
429
|
+
|
|
430
|
+
Intended use case for **always**: python imports or informations that
|
|
431
|
+
are needed afterwards and do not change anything on systems.
|
|
432
|
+
You want to have these available even if using --jump|-j feature.
|
|
433
|
+
|
|
434
|
+
Intended use case for **cleanup**: Remove temporary files or artifacts.
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
## ENVIRONMENT
|
|
438
|
+
|
|
439
|
+
**AUTOMAGIX_CONFIG**: Specify the path to the configuration file.
|
|
440
|
+
Default is "~/.automagix.cfg.yaml".
|
|
441
|
+
|
|
442
|
+
**AUTOMAGIX_**_config-variable-in-upper-case_: Set or overwrite the
|
|
443
|
+
corresponding configuration value. See **CONFIGURATION** section.
|
|
444
|
+
Works only for string and boolean values!
|
|
445
|
+
String values (case-insensitive 'true' or 'false') are converted
|
|
446
|
+
to `True` or `False` in Python, if the fields expects a boolean.
|
|
447
|
+
**All other values (int, float, dict, list, ...) are ignored!**
|
|
448
|
+
|
|
449
|
+
**AUTOMAGIX_TIME**: Set this to an arbitrary value to print the times
|
|
450
|
+
for the single steps and the whole script, e.g. `AUTOMAGIX_TIME=true`.
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
# TIPS & TRICKS
|
|
454
|
+
|
|
455
|
+
### YAML Syntax
|
|
456
|
+
|
|
457
|
+
For multiline commands and variables YAML offers different possibilities
|
|
458
|
+
to write multiline strings. A look at https://yaml-multiline.info/ might
|
|
459
|
+
be helpful.
|
|
460
|
+
|
|
461
|
+
### PERSISTENT_VARS
|
|
462
|
+
|
|
463
|
+
If you want to access variables in **python** action you defined in
|
|
464
|
+
preceeding command, you can use the **PERSISTENT_VARS** dictionary
|
|
465
|
+
(shortcut: **PVARS**).
|
|
466
|
+
This is added to the local scope of **python** actions and the
|
|
467
|
+
dictonary keys are also available as attributes.
|
|
468
|
+
Examples:
|
|
469
|
+
- To make all local variables of the actual command persistent use
|
|
470
|
+
`PERSISTENT_VARS.update(locals())`.
|
|
471
|
+
- To delete one persistent variable named "myvar" use
|
|
472
|
+
`del PERSISTENT_VARS['myvar']`
|
|
473
|
+
- To make variable "v2" persistent use `PERSISTENT_VARS['v2'] = v2`
|
|
474
|
+
or `PERSISTENT_VARS.v2 = v2`
|
|
475
|
+
- Use the shortcut like `PVARS.v2 = v2`
|
|
476
|
+
|
|
477
|
+
**Note: Following works ONLY with the shortcut "PVARS"**:
|
|
478
|
+
|
|
479
|
+
You can use these variables also as condition or as normal automagix
|
|
480
|
+
variable in curly brackets by using the shortcut and the attribute notation:
|
|
481
|
+
|
|
482
|
+
- python: PVARS.cond = some_function()
|
|
483
|
+
- PVARS.cond?local: echo 'This is only printed if "some_function" evaluates to "True"'
|
|
484
|
+
- PVARS.cond!?local: echo 'And this is printed if "some_function" evaluates to "False"'
|
|
485
|
+
- local: echo "The condition variable contains the value '{PVARS.cond}'."
|
|
486
|
+
|
|
487
|
+
*Since version 2.4.0 making variables global does not work any longer!*
|
|
488
|
+
|
|
489
|
+
### Abort and Skip Exceptions
|
|
490
|
+
|
|
491
|
+
To abort the current automagix and jump to the next batch item you can
|
|
492
|
+
raise the `SkipBatchItemException`. For aborting the whole automagix
|
|
493
|
+
process raise `AbortException(return_code: int)`. In both cases the
|
|
494
|
+
cleanup pipeline is executed. Same is the case for selecting
|
|
495
|
+
`a`:abort or `c`:continue when asked (interactive or error).
|
|
496
|
+
|
|
497
|
+
### Logging / Saving the output
|
|
498
|
+
|
|
499
|
+
**automagix** offers no own capability to log the output to a log file or
|
|
500
|
+
save it otherwise.
|
|
501
|
+
|
|
502
|
+
If you have _GNU screen_ installed, you may start a screen session with
|
|
503
|
+
`-L` and optional `-Logfile LOGFILE` in which you start **automagix**.
|
|
504
|
+
(This is how it works with "parallel processing", see **EXTRAS** section.)
|
|
505
|
+
|
|
506
|
+
A different approach is to use `tee`, e.g. `automagix [script file + options] 2>&1 | tee auto.log`.
|
|
507
|
+
Different to the screen approach this seems not to capture your input.
|
|
508
|
+
|
|
509
|
+
# BEST PRACTISES
|
|
510
|
+
|
|
511
|
+
There are different ways to start scripting with **automagix**. The
|
|
512
|
+
author's approach is mainly to consider the process and simply write
|
|
513
|
+
down, what to do (manual steps for complex or not automated steps)
|
|
514
|
+
and which commands to use.
|
|
515
|
+
Then start **automagix** in interactive mode (-i) and adjust the
|
|
516
|
+
single steps one by one. Replace manual steps, if suitable. Whenever
|
|
517
|
+
adjustment is needed, abort, adjust and restart **automagix** with
|
|
518
|
+
jump (-j) to the adjusted step.
|
|
519
|
+
From **automagix** 1.13.0 on you can use the reload scriptfile feature
|
|
520
|
+
instead. When asked for options (either because a command failed or
|
|
521
|
+
you are in interactive mode) you can use **-R** to reload the
|
|
522
|
+
scriptfile. If lines in the scriptfile have changed, or you need to
|
|
523
|
+
repeat steps, you can use R+/-$number to reload and adjust the
|
|
524
|
+
restart point (available since **automagix** 1.14.0). NOTICE: If using
|
|
525
|
+
vars-file, this reloads the script ONLY the active CSV row!
|
|
526
|
+
|
|
527
|
+
Repeat this procedure to automate more and more and increase quality,
|
|
528
|
+
whenever you feel like it.
|
|
529
|
+
|
|
530
|
+
Consider to put often used paths or code sequences in automagix
|
|
531
|
+
variables for better readability.
|
|
532
|
+
Do the same with variable content like URLs, to make it possible to
|
|
533
|
+
overwrite it by command line options. Where ever possible prefer to
|
|
534
|
+
use functions to determine already available information, such as BW
|
|
535
|
+
metadata, instead of defining things explicitly. This will make
|
|
536
|
+
things easier when using the script with different systems /
|
|
537
|
+
parameters.
|
|
538
|
+
|
|
539
|
+
Preferred way of using **automagix** is to put often used and complex
|
|
540
|
+
algorithms in python libraries and import them. Advantage of this
|
|
541
|
+
approach is that you can use your implemented functions multiple
|
|
542
|
+
times and build up a toolbox of nice functionality over time.
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
# NOTES
|
|
546
|
+
|
|
547
|
+
**Manual steps** will always cause automagix to stop and wait for
|
|
548
|
+
user input.
|
|
549
|
+
|
|
550
|
+
Be careful with **assignments** containing line breaks (echo, ...).
|
|
551
|
+
Using the variables may lead to unexpected behaviour or errors.
|
|
552
|
+
From version 1.14.0 on trailing new lines in **assignments**
|
|
553
|
+
of Shell commands (_local_, _remote@_) are removed.
|
|
554
|
+
|
|
555
|
+
Assignments containing **null bytes** are currently not supported.
|
|
556
|
+
|
|
557
|
+
Because the **always** pipeline should not change anything, aborting
|
|
558
|
+
while running this pipeline will not trigger a cleanup.
|
|
559
|
+
|
|
560
|
+
If you want to abort the **pipeline** without triggering the
|
|
561
|
+
**cleanup** pipeline, use CRTL+C.
|
|
562
|
+
|
|
563
|
+
While **aborting remote functions** automagix is not
|
|
564
|
+
able to determine still running processes invoked by the function,
|
|
565
|
+
because it only checks the processes for the commands (in this case
|
|
566
|
+
the function name) which is called in the pipeline.
|
|
567
|
+
|
|
568
|
+
User input questions are of following categories:
|
|
569
|
+
- [MS] **M**anual **S**tep
|
|
570
|
+
- [CF] **C**ommand **F**ailed
|
|
571
|
+
- [PF] **P**artial command **F**ailed (BW groups)
|
|
572
|
+
- [RR] **R**emote process still **R**unning
|
|
573
|
+
- [SE] **S**yntax **E**rror
|
|
574
|
+
|
|
575
|
+
The terminal (T) answer starts an interactive Bash-Shell.
|
|
576
|
+
Therefore .bashrc is executed, but the command prompt (PS1) is
|
|
577
|
+
replaced to indicate, that we are still in an automagix process.
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
# EXTRAS
|
|
581
|
+
|
|
582
|
+
## Parallel processing
|
|
583
|
+
Requirement: GNU screen installed and accessible via `screen` command in bash.
|
|
584
|
+
|
|
585
|
+
This **automagix** version has the option to process multiple **automagix** instances at a time.
|
|
586
|
+
This is achieved by starting multiple [GNU screen](https://www.gnu.org/software/screen/) sessions.
|
|
587
|
+
Please make yourself comfortable with the screen controls before using this feature to avoid getting lost.
|
|
588
|
+
|
|
589
|
+
The main programm stays in a loop while attaching to the screen sessions and you will come back to it
|
|
590
|
+
if you detach a screen session. The **automagix-manager** runs in its own screen session and is
|
|
591
|
+
responsible for starting the automagix screens and status updates.
|
|
592
|
+
|
|
593
|
+
By default the programm starts with 10 parallel automagix instances. Use the main programm loop controls
|
|
594
|
+
to change the number of allowed parallel sessions (pressing 'm' followed by your desired number).
|
|
595
|
+
|
|
596
|
+
If you force the programm to terminate (e.g. keyboard interrupt, process kill, ...),
|
|
597
|
+
check for still running screen processes via `screen -list`. They are independent and may continue
|
|
598
|
+
running. Cleanup manually, if necessary.
|
|
599
|
+
|
|
600
|
+
The screens write their output to log files in the specified **logfile_dir** (see **CONFIGURATION** section).
|
|
601
|
+
These logfiles contain the escape sequences that are used to provide the colored output an the terminal.
|
|
602
|
+
You can use a pager that supports interpreting these sequences like the terminal to have a similar
|
|
603
|
+
experience (`more` or `less -r` worked for me).
|
|
604
|
+
|
|
605
|
+
## Shell completion (experimental)
|
|
606
|
+
Automagix supports shell completion for parameters and the script directory via [argcomplete](https://github.com/kislyuk/argcomplete).
|
|
607
|
+
|
|
608
|
+
Therefor follow the installation instructions for argcomplete, which is at the current time
|
|
609
|
+
|
|
610
|
+
pip install argcomplete
|
|
611
|
+
|
|
612
|
+
and either global activation via executing
|
|
613
|
+
|
|
614
|
+
activate-global-python-argcomplete
|
|
615
|
+
|
|
616
|
+
or activation for automagix (e.g. in `.bashrc` or `.zshrc`)
|
|
617
|
+
|
|
618
|
+
eval "$(register-python-argcomplete automagix)"
|
|
619
|
+
|
|
620
|
+
Automagix will recognize the installed module and offer the completion automatically.
|
|
621
|
+
|
|
622
|
+
## Progress bar (experimental)
|
|
623
|
+
You can activate an "apt-like" progress bar based on the amount of commands.
|
|
624
|
+
There are two types of progress bars *Basic* and *Tqdm*, which can be activated
|
|
625
|
+
by setting the configuration option `progress_bar` to the corresponding value
|
|
626
|
+
(config file or environment). "Tqdm" requires additional installation of the tqdm
|
|
627
|
+
Python library (`pip install tqdm`).
|
|
628
|
+
|
|
629
|
+
The status on the right displays `[elapsed time<remaining time, rate]`,
|
|
630
|
+
where rate is percentage/second if fast and second/percentage if slow.
|
|
631
|
+
|
|
632
|
+
Note, that using commands that heavily modify the terminal behaviour/output
|
|
633
|
+
(such as `top`, `watch`, `glances`, ...), may lead to a unreadable
|
|
634
|
+
or undesirable output. It might be a better idea to encourage the user
|
|
635
|
+
to open a separate terminal and type these commands there.
|
|
636
|
+
|
|
637
|
+
Using automagix itself as command should work, but may lead to confusing
|
|
638
|
+
output as well. Note, that the progress bar will be overwritten by the
|
|
639
|
+
new automagix instance for the duration of the automagix command.
|