Blame


1 03d8f521 2025-05-27 xs #!/bin/sh
2 138e225e 2025-06-04 xs # ISC License
3 138e225e 2025-06-04 xs #
4 138e225e 2025-06-04 xs # Copyright 2025 xs <xs@inda.re>
5 138e225e 2025-06-04 xs #
6 138e225e 2025-06-04 xs # Permission to use, copy, modify, and/or distribute this software for any
7 138e225e 2025-06-04 xs # purpose with or without fee is hereby granted, provided that the above
8 138e225e 2025-06-04 xs # copyright notice and this permission notice appear in all copies.
9 138e225e 2025-06-04 xs #
10 138e225e 2025-06-04 xs # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11 138e225e 2025-06-04 xs # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
12 138e225e 2025-06-04 xs # FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13 138e225e 2025-06-04 xs # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 138e225e 2025-06-04 xs # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15 138e225e 2025-06-04 xs # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 138e225e 2025-06-04 xs # PERFORMANCE OF THIS SOFTWARE.
17 8a9cbf90 2025-06-04 xs
18 46924c01 2025-05-28 xs # shellcheck disable=SC2046,SC2031
19 8a9cbf90 2025-06-04 xs
20 03d8f521 2025-05-27 xs # Global configuration
21 03d8f521 2025-05-27 xs # ====================
22 8a9cbf90 2025-06-04 xs
23 8e44e3d4 2025-06-25 xs : "${ZSH_VERSION:=}"
24 8e44e3d4 2025-06-25 xs R7_DEBUG=no
25 a4759196 2025-06-13 xs VERSION=0.2.0
26 8e44e3d4 2025-06-25 xs _init_pwd="$PWD"
27 03d8f521 2025-05-27 xs
28 46924c01 2025-05-28 xs # shellcheck disable=SC2031
29 46924c01 2025-05-28 xs _init_env() {
30 46924c01 2025-05-28 xs _debug _INIT_ENV
31 8e44e3d4 2025-06-25 xs cd "$_init_pwd" || _fail "Unable to cd to '$_init_pwd'"
32 46924c01 2025-05-28 xs
33 46924c01 2025-05-28 xs # Here is the default configuration
34 46924c01 2025-05-28 xs : "${R7_DEBUG:=no}"
35 46924c01 2025-05-28 xs : "${R7_DRYRUN:=no}"
36 31e019a2 2025-05-31 xs : "${R7_GROUP_ALLPREFIX:=no}"
37 31e019a2 2025-05-31 xs : "${R7_GROUP_SUMMARY:=no}"
38 730e151b 2025-06-02 xs : "${R7_GROUP_EXITONERROR:=no}"
39 46924c01 2025-05-28 xs : "${R7_PARALLEL:=no}"
40 46924c01 2025-05-28 xs : "${R7_PREFIX:=install state doc}"
41 31e019a2 2025-05-31 xs : "${R7_SHOWOUTPUT:=no}"
42 8e44e3d4 2025-06-25 xs : "${R7_WORKDIR:=$_init_pwd}"
43 46924c01 2025-05-28 xs : "${R7_SITE_CONFIG:=$R7_WORKDIR/site-config}"
44 31e019a2 2025-05-31 xs : "${R7_OUTPUTDIR:=$R7_WORKDIR/_output}"
45 31e019a2 2025-05-31 xs : "${SSH_CONFIG_DIR:=$R7_WORKDIR/.ssh}"
46 46924c01 2025-05-28 xs : "${SSH_CONFIG_FILE:=$R7_WORKDIR/.ssh/config}"
47 31e019a2 2025-05-31 xs : "${SSH_CONTROL_DIR:=$SSH_CONFIG_DIR/control}"
48 46924c01 2025-05-28 xs : "${SSH_IDENTITY_FILE:=$R7_WORKDIR/.ssh/id_ed25519_r7}"
49 f83445b1 2025-05-30 xs : "${SSH_KNOWN_HOSTS:=$R7_WORKDIR/.ssh/known_hosts}"
50 31e019a2 2025-05-31 xs : "${SSH_CONNECT_TIMEOUT:=3}"
51 46924c01 2025-05-28 xs
52 46924c01 2025-05-28 xs _debug ENVIRONMENT
53 46924c01 2025-05-28 xs
54 46924c01 2025-05-28 xs # Validate environment
55 46924c01 2025-05-28 xs if test "$R7_DEBUG" = yes; then
56 46924c01 2025-05-28 xs set | grep -e '^R7_' -e '^SSH' 1>&2
57 46924c01 2025-05-28 xs fi
58 46924c01 2025-05-28 xs
59 46924c01 2025-05-28 xs for param in "$R7_DEBUG" "$R7_DRYRUN" "$R7_PARALLEL"; do
60 46924c01 2025-05-28 xs case $param in
61 46924c01 2025-05-28 xs yes | no) : ;;
62 46924c01 2025-05-28 xs *) _fail "Invalid parameter value: '$param'" ;;
63 46924c01 2025-05-28 xs esac
64 46924c01 2025-05-28 xs done
65 46924c01 2025-05-28 xs
66 46924c01 2025-05-28 xs R7_WORKDIR_tmp=$(_resolv_dir "$R7_WORKDIR")
67 730e151b 2025-06-02 xs test -d "$R7_WORKDIR_tmp" || _error "Working directory not found: '$R7_WORKDIR'"
68 46924c01 2025-05-28 xs R7_WORKDIR=$R7_WORKDIR_tmp
69 46924c01 2025-05-28 xs R7_RUNDIR=$R7_WORKDIR/_run
70 46924c01 2025-05-28 xs R7_OUTPUTDIR=$R7_WORKDIR/_output
71 46924c01 2025-05-28 xs
72 46924c01 2025-05-28 xs R7_SITE_CONFIG_tmp=$(_resolv_file "$R7_SITE_CONFIG")
73 730e151b 2025-06-02 xs test -f "$R7_SITE_CONFIG_tmp" || _error "Site configuration not found: '$R7_SITE_CONFIG'"
74 46924c01 2025-05-28 xs R7_SITE_CONFIG=$R7_SITE_CONFIG_tmp
75 46924c01 2025-05-28 xs
76 46924c01 2025-05-28 xs SSH_CONFIG_FILE_tmp=$(_resolv_file "$SSH_CONFIG_FILE")
77 730e151b 2025-06-02 xs test -f "$SSH_CONFIG_FILE_tmp" || _error "Unable to read SSH configuration: '$SSH_CONFIG_FILE'"
78 46924c01 2025-05-28 xs SSH_CONFIG_FILE=$SSH_CONFIG_FILE_tmp
79 46924c01 2025-05-28 xs
80 46924c01 2025-05-28 xs SSH_IDENTITY_FILE_tmp=$(_resolv_file "$SSH_IDENTITY_FILE")
81 730e151b 2025-06-02 xs test -f "$SSH_IDENTITY_FILE_tmp" || _error "Unable to read SSH identity file: '$SSH_IDENTITY_FILE'"
82 46924c01 2025-05-28 xs SSH_IDENTITY_FILE=$SSH_IDENTITY_FILE_tmp
83 46924c01 2025-05-28 xs
84 0253bef1 2025-05-29 xs R7_ENV_READY=yes
85 46924c01 2025-05-28 xs unset R7_WORKDIR_tmp R7_SITE_CONFIG_tmp SSH_CONFIG_FILE_tmp SSH_IDENTITY_FILE_tmp
86 46924c01 2025-05-28 xs }
87 46924c01 2025-05-28 xs
88 03d8f521 2025-05-27 xs # Interface
89 03d8f521 2025-05-27 xs # =========
90 03d8f521 2025-05-27 xs
91 46924c01 2025-05-28 xs _fail() {
92 730e151b 2025-06-02 xs printf "FAILURE: %s\n" "$*" >&2
93 46924c01 2025-05-28 xs exit 99
94 46924c01 2025-05-28 xs }
95 46924c01 2025-05-28 xs
96 730e151b 2025-06-02 xs _error() {
97 730e151b 2025-06-02 xs printf "ERROR: %s\n" "$*" >&2
98 730e151b 2025-06-02 xs }
99 730e151b 2025-06-02 xs
100 46924c01 2025-05-28 xs _debug() {
101 f83445b1 2025-05-30 xs test "$R7_DEBUG" = yes && printf %s\\n "${*:-$(cat -)}" >&2
102 46924c01 2025-05-28 xs }
103 46924c01 2025-05-28 xs
104 0253bef1 2025-05-29 xs info() {
105 0253bef1 2025-05-29 xs if test "$R7_ENV_READY" = yes; then
106 0253bef1 2025-05-29 xs cd "$R7_WORKDIR" || return 2
107 f6bdfddc 2025-06-03 xs _trace_id_last=$(trace_id_last)
108 f6bdfddc 2025-06-03 xs if test -n "$_trace_id_last"; then
109 f6bdfddc 2025-06-03 xs printf -- "- (%s) - in %s the %s\n" \
110 f6bdfddc 2025-06-03 xs "$_trace_id_last" "$(basename "$R7_WORKDIR")" "$(_epoch "$_trace_id_last")"
111 f6bdfddc 2025-06-03 xs nodes_active | sed 's/^/ - (active) /'
112 31e019a2 2025-05-31 xs echo
113 0253bef1 2025-05-29 xs fi
114 31e019a2 2025-05-31 xs output_dump
115 31e019a2 2025-05-31 xs summary
116 0253bef1 2025-05-29 xs fi
117 730e151b 2025-06-02 xs return 0
118 0253bef1 2025-05-29 xs }
119 0253bef1 2025-05-29 xs
120 46924c01 2025-05-28 xs alias help=usage
121 03d8f521 2025-05-27 xs usage() {
122 03d8f521 2025-05-27 xs cat <<eof
123 2f0c97a2 2025-06-04 xs version: $VERSION
124 730e151b 2025-06-02 xs usage: $0 [options] [command [arguments...]]
125 03d8f521 2025-05-27 xs usage options:
126 03d8f521 2025-05-27 xs -h Show usage and exit
127 03d8f521 2025-05-27 xs -d Debug
128 03d8f521 2025-05-27 xs -i SSH identity file
129 03d8f521 2025-05-27 xs -F SSH client configuration file
130 03d8f521 2025-05-27 xs -w Work directory where to find ./nodes and ./groups
131 03d8f521 2025-05-27 xs -r Run directory, default to ./_run
132 03d8f521 2025-05-27 xs -o Output directory, default to ./_output
133 03d8f521 2025-05-27 xs -c Site configuration file, default to ./site-config
134 03d8f521 2025-05-27 xs -n Dry run, prevent any host modification
135 730e151b 2025-06-02 xs -e Exit the group execution on the error function
136 03d8f521 2025-05-27 xs -p Run each host in parallel per group call
137 0253bef1 2025-05-29 xs -O Show output interactively
138 4296d94d 2025-06-07 xs -P Prefix, can contain whole function names
139 0253bef1 2025-05-29 xs -a Select all available prefixes for a group command
140 0253bef1 2025-05-29 xs -s Output-dump and summary are applied after a group command
141 03d8f521 2025-05-27 xs
142 03d8f521 2025-05-27 xs commands:
143 03d8f521 2025-05-27 xs run-config Run the site configuration
144 03d8f521 2025-05-27 xs group Deploy specified group to hosts
145 03d8f521 2025-05-27 xs output-dump Dump the run directory to the output directory
146 03d8f521 2025-05-27 xs output Consult the output
147 0253bef1 2025-05-29 xs summary Summary of errors and changes
148 03d8f521 2025-05-27 xs digraph-host Produce digraph host
149 730e151b 2025-06-02 xs digraph-ssh Produce SSH IDs digraph
150 730e151b 2025-06-02 xs import Import TARGET host in current nodes directory
151 87bce7c5 2025-05-30 xs info Default command showing active nodes and summary
152 31e019a2 2025-05-31 xs init Initialize a new work directory
153 03d8f521 2025-05-27 xs
154 03d8f521 2025-05-27 xs site-config format:
155 03d8f521 2025-05-27 xs prefix [prefix...] # Define the prefix to be executed in order
156 03d8f521 2025-05-27 xs group groupname ['.*'|hostname...] # Deploy specified group to hosts
157 03d8f521 2025-05-27 xs
158 03d8f521 2025-05-27 xs eof
159 03d8f521 2025-05-27 xs }
160 03d8f521 2025-05-27 xs
161 03d8f521 2025-05-27 xs # shellcheck disable=SC2086
162 46924c01 2025-05-28 xs _main() {
163 730e151b 2025-06-02 xs test -n "$ZSH_VERSION" && {
164 730e151b 2025-06-02 xs echo >&2 "ZSH is unsupported. Exiting."
165 8a9cbf90 2025-06-04 xs return 3
166 730e151b 2025-06-02 xs }
167 730e151b 2025-06-02 xs while getopts 'P:F:r:o:i:w:c:npdseaOh' arg; do
168 03d8f521 2025-05-27 xs case $arg in
169 03d8f521 2025-05-27 xs h)
170 03d8f521 2025-05-27 xs usage
171 8a9cbf90 2025-06-04 xs return 0
172 03d8f521 2025-05-27 xs ;;
173 46924c01 2025-05-28 xs d)
174 46924c01 2025-05-28 xs R7_DEBUG=yes
175 46924c01 2025-05-28 xs _debug "R7 DEBUG $VERSION"
176 46924c01 2025-05-28 xs ;;
177 03d8f521 2025-05-27 xs i) SSH_IDENTITY_FILE=$OPTARG ;;
178 03d8f521 2025-05-27 xs F) SSH_CONFIG_FILE=$OPTARG ;;
179 46924c01 2025-05-28 xs w) R7_WORKDIR=$OPTARG ;;
180 46924c01 2025-05-28 xs r) R7_RUNDIR=$OPTARG ;;
181 46924c01 2025-05-28 xs o) R7_OUTPUTDIR=$OPTARG ;;
182 0253bef1 2025-05-29 xs s) R7_GROUP_SUMMARY=yes ;;
183 0253bef1 2025-05-29 xs a) R7_GROUP_ALLPREFIX=yes ;;
184 730e151b 2025-06-02 xs e) R7_GROUP_EXITONERROR=yes ;;
185 46924c01 2025-05-28 xs c) R7_SITE_CONFIG=$OPTARG ;;
186 46924c01 2025-05-28 xs n)
187 46924c01 2025-05-28 xs R7_DRYRUN=yes
188 46924c01 2025-05-28 xs _debug "MODE DRYRUN"
189 46924c01 2025-05-28 xs ;;
190 46924c01 2025-05-28 xs p) R7_PARALLEL=yes ;;
191 03d8f521 2025-05-27 xs P)
192 46924c01 2025-05-28 xs R7_PREFIX=$OPTARG
193 46924c01 2025-05-28 xs prefix $R7_PREFIX
194 03d8f521 2025-05-27 xs ;;
195 46924c01 2025-05-28 xs O) R7_SHOWOUTPUT=yes ;;
196 03d8f521 2025-05-27 xs *)
197 0253bef1 2025-05-29 xs usage
198 0253bef1 2025-05-29 xs echo 1>&2 "Unknown option '$arg'"
199 03d8f521 2025-05-27 xs exit 2
200 03d8f521 2025-05-27 xs ;;
201 03d8f521 2025-05-27 xs esac
202 03d8f521 2025-05-27 xs done
203 03d8f521 2025-05-27 xs shift $((OPTIND - 1))
204 46924c01 2025-05-28 xs
205 03d8f521 2025-05-27 xs case $1 in
206 46924c01 2025-05-28 xs init | workdir-init)
207 730e151b 2025-06-02 xs shift
208 730e151b 2025-06-02 xs _workdir_init "$@"
209 46924c01 2025-05-28 xs exit $?
210 46924c01 2025-05-28 xs ;;
211 46924c01 2025-05-28 xs esac
212 87bce7c5 2025-05-30 xs
213 46924c01 2025-05-28 xs _init_env
214 46924c01 2025-05-28 xs
215 46924c01 2025-05-28 xs case $1 in
216 730e151b 2025-06-02 xs rc | run-config) run_config ;;
217 03d8f521 2025-05-27 xs group)
218 03d8f521 2025-05-27 xs shift
219 46924c01 2025-05-28 xs trace_id=$(_trace_id_new)
220 0253bef1 2025-05-29 xs if test "$R7_GROUP_ALLPREFIX" = yes; then
221 0253bef1 2025-05-29 xs prefix $(group_prefixes "$1")
222 87bce7c5 2025-05-30 xs else
223 87bce7c5 2025-05-30 xs prefix $R7_PREFIX
224 0253bef1 2025-05-29 xs fi
225 03d8f521 2025-05-27 xs group "$@"
226 0253bef1 2025-05-29 xs if test "$R7_GROUP_SUMMARY" = yes; then
227 0253bef1 2025-05-29 xs output_dump
228 0253bef1 2025-05-29 xs summary
229 0253bef1 2025-05-29 xs fi
230 03d8f521 2025-05-27 xs ;;
231 87bce7c5 2025-05-30 xs info) info ;;
232 688c9bfd 2025-06-03 xs import)
233 688c9bfd 2025-06-03 xs shift
234 688c9bfd 2025-06-03 xs import "$@"
235 688c9bfd 2025-06-03 xs ;;
236 87bce7c5 2025-05-30 xs out | output)
237 87bce7c5 2025-05-30 xs shift
238 87bce7c5 2025-05-30 xs output "$@"
239 87bce7c5 2025-05-30 xs ;;
240 87bce7c5 2025-05-30 xs outdump | output-dump) output_dump ;;
241 0253bef1 2025-05-29 xs summary) summary ;;
242 03d8f521 2025-05-27 xs digraph-host)
243 46924c01 2025-05-28 xs prefix $R7_PREFIX
244 03d8f521 2025-05-27 xs digraph_host
245 03d8f521 2025-05-27 xs ;;
246 730e151b 2025-06-02 xs digraph-ssh)
247 730e151b 2025-06-02 xs digraph_ssh_id_hosts
248 0253bef1 2025-05-29 xs ;;
249 0551e9c2 2025-06-04 xs html) html "$@" ;;
250 8e44e3d4 2025-06-25 xs '') cd "$R7_WORKDIR" && info ;;
251 03d8f521 2025-05-27 xs *)
252 03d8f521 2025-05-27 xs case $0 in
253 730e151b 2025-06-02 xs -) exit 33 ;;
254 03d8f521 2025-05-27 xs *r7)
255 46924c01 2025-05-28 xs echo 1>&2 "Unknown command '$1'"
256 46924c01 2025-05-28 xs usage
257 03d8f521 2025-05-27 xs exit 2
258 03d8f521 2025-05-27 xs ;;
259 730e151b 2025-06-02 xs *) prefix $R7_PREFIX ;;
260 03d8f521 2025-05-27 xs esac
261 03d8f521 2025-05-27 xs ;;
262 03d8f521 2025-05-27 xs esac
263 03d8f521 2025-05-27 xs }
264 03d8f521 2025-05-27 xs
265 46924c01 2025-05-28 xs _resolv_dir() {
266 46924c01 2025-05-28 xs if test -d "$1"; then
267 46924c01 2025-05-28 xs cd "$1" || return 2
268 46924c01 2025-05-28 xs printf %s "$PWD"
269 46924c01 2025-05-28 xs fi
270 46924c01 2025-05-28 xs }
271 46924c01 2025-05-28 xs
272 46924c01 2025-05-28 xs _resolv_file() {
273 46924c01 2025-05-28 xs if test -f "$1"; then
274 46924c01 2025-05-28 xs cd "${1%/*}" || return 2
275 46924c01 2025-05-28 xs printf %s "$PWD/${1##*/}"
276 46924c01 2025-05-28 xs fi
277 46924c01 2025-05-28 xs }
278 46924c01 2025-05-28 xs
279 46924c01 2025-05-28 xs # shellcheck disable=SC2030
280 46924c01 2025-05-28 xs _workdir_init() (
281 730e151b 2025-06-02 xs _debug _WORKDIR_INIT "$PWD" "$R7_WORKDIR"
282 730e151b 2025-06-02 xs if test -n "$R7_WORKDIR"; then
283 730e151b 2025-06-02 xs mkdir -p "$R7_WORKDIR" || _fail "Unable to create directory: '$R7_WORKDIR'"
284 730e151b 2025-06-02 xs cd "$R7_WORKDIR" || _fail "Unable to cd to directory: '$R7_WORKDIR'"
285 730e151b 2025-06-02 xs R7_WORKDIR=$PWD
286 730e151b 2025-06-02 xs fi
287 730e151b 2025-06-02 xs R7_WORKDIR=$PWD
288 46924c01 2025-05-28 xs mkdir -p groups
289 46924c01 2025-05-28 xs mkdir -p nodes
290 730e151b 2025-06-02 xs mkdir -p .ssh/control
291 730e151b 2025-06-02 xs : "${SSH_CONFIG_FILE:=$R7_WORKDIR/.ssh/config}"
292 730e151b 2025-06-02 xs : "${SSH_IDENTITY_FILE:=$R7_WORKDIR/.ssh/id_ed25519_r7}"
293 46924c01 2025-05-28 xs R7_SITE_CONFIG=./site-config
294 46924c01 2025-05-28 xs if ! test -f "$R7_SITE_CONFIG"; then
295 46924c01 2025-05-28 xs cat >"$R7_SITE_CONFIG" <<-eof
296 46924c01 2025-05-28 xs # Example r7 site configuration
297 730e151b 2025-06-02 xs group common '.*'
298 46924c01 2025-05-28 xs eof
299 46924c01 2025-05-28 xs fi
300 46924c01 2025-05-28 xs if ! test -f "$SSH_CONFIG_FILE"; then
301 46924c01 2025-05-28 xs cat >"$SSH_CONFIG_FILE" <<eof
302 46924c01 2025-05-28 xs # Example SSH client configuration
303 46924c01 2025-05-28 xs Host *
304 46924c01 2025-05-28 xs AddKeysToAgent yes
305 46924c01 2025-05-28 xs BatchMode yes
306 46924c01 2025-05-28 xs ConnectTimeout 3
307 46924c01 2025-05-28 xs ConnectionAttempts 1
308 46924c01 2025-05-28 xs ControlMaster auto
309 730e151b 2025-06-02 xs #ControlPath $R7_WORKDIR/.ssh/control/%C
310 730e151b 2025-06-02 xs ControlPath $R7_WORKDIR/.ssh/control/%r@%h:%p
311 46924c01 2025-05-28 xs ControlPersist 2m
312 46924c01 2025-05-28 xs IdentityFile $SSH_IDENTITY_FILE
313 46924c01 2025-05-28 xs StrictHostKeyChecking yes
314 46924c01 2025-05-28 xs User root
315 46924c01 2025-05-28 xs UserKnownHostsFile $R7_WORKDIR/.ssh/known_hosts
316 46924c01 2025-05-28 xs eof
317 46924c01 2025-05-28 xs fi
318 31e019a2 2025-05-31 xs touch "${SSH_IDENTITY_FILE}" "${SSH_IDENTITY_FILE}.pub"
319 46924c01 2025-05-28 xs touch .ssh/known_hosts
320 46924c01 2025-05-28 xs echo Created:
321 46924c01 2025-05-28 xs find "$PWD" -exec printf -- "\t- %s\n" {} +
322 46924c01 2025-05-28 xs )
323 46924c01 2025-05-28 xs
324 46924c01 2025-05-28 xs # SSH functions
325 03d8f521 2025-05-27 xs # =============
326 03d8f521 2025-05-27 xs
327 03d8f521 2025-05-27 xs ssh() (
328 46924c01 2025-05-28 xs _debug "SSH $*"
329 03d8f521 2025-05-27 xs /usr/bin/ssh "-oConnectTimeout=$SSH_CONNECT_TIMEOUT" -F "$SSH_CONFIG_FILE" "$@"
330 03d8f521 2025-05-27 xs )
331 03d8f521 2025-05-27 xs
332 f83445b1 2025-05-30 xs alias ssh-debug=ssh_debug
333 f83445b1 2025-05-30 xs ssh_debug() {
334 f83445b1 2025-05-30 xs _debug "SSH $*"
335 8e44e3d4 2025-06-25 xs ssh -vvv "$@"
336 f83445b1 2025-05-30 xs }
337 f83445b1 2025-05-30 xs
338 f83445b1 2025-05-30 xs alias ssh-known-hosts=ssh_known_hosts
339 f83445b1 2025-05-30 xs ssh_known_hosts() {
340 f83445b1 2025-05-30 xs /usr/bin/ssh-keygen -lv -f "${SSH_KNOWN_HOSTS:-$R7_WORKDIR/.ssh/known_hosts}"
341 f83445b1 2025-05-30 xs }
342 f83445b1 2025-05-30 xs
343 f83445b1 2025-05-30 xs alias ssh-authorized-keys-reset=ssh_authorized_keys_reset
344 f83445b1 2025-05-30 xs alias ssh-authreset=ssh_authorized_keys_reset
345 f83445b1 2025-05-30 xs ssh_authorized_keys_reset() {
346 f83445b1 2025-05-30 xs ssh -o BatchMode=no "$@" "
347 f83445b1 2025-05-30 xs mkdir -p ~/.ssh
348 f83445b1 2025-05-30 xs chmod 700 ~/.ssh
349 f83445b1 2025-05-30 xs touch ~/.ssh/authorized_keys
350 f83445b1 2025-05-30 xs chmod 600 ~/.ssh/authorized_keys
351 f83445b1 2025-05-30 xs echo '$(cat "$SSH_IDENTITY_FILE.pub")' >~/.ssh/authorized_keys
352 f83445b1 2025-05-30 xs "
353 f83445b1 2025-05-30 xs }
354 f83445b1 2025-05-30 xs
355 f83445b1 2025-05-30 xs alias ssh-accept-new=ssh_accept_new
356 f83445b1 2025-05-30 xs ssh_accept_new() {
357 8e44e3d4 2025-06-25 xs ssh -F "$SSH_CONFIG_FILE" -o StrictHostKeyChecking=accept-new "$@" :
358 f83445b1 2025-05-30 xs }
359 f83445b1 2025-05-30 xs
360 f83445b1 2025-05-30 xs alias ssh-control-master-clean=ssh_control_master_clean
361 f83445b1 2025-05-30 xs ssh_control_master_clean() {
362 31e019a2 2025-05-31 xs find "$SSH_CONTROL_DIR" -type f -exec rm {} \;
363 f83445b1 2025-05-30 xs }
364 f83445b1 2025-05-30 xs
365 f83445b1 2025-05-30 xs alias ssh-users=ssh_users
366 f83445b1 2025-05-30 xs ssh_users() {
367 730e151b 2025-06-02 xs cd "$R7_WORKDIR/nodes" || _fail "Unable to cd to '$R7_WORKDIR/nodes'."
368 730e151b 2025-06-02 xs find ./* -type f -name "authorized_keys_*" |
369 3aa5672d 2025-06-04 xs sed 's;^./;;' |
370 f83445b1 2025-05-30 xs sort | while read -r keyfile; do
371 f83445b1 2025-05-30 xs echo "- $keyfile:"
372 f83445b1 2025-05-30 xs grep -v "^#" "$R7_WORKDIR/nodes/$keyfile"
373 f83445b1 2025-05-30 xs done
374 f83445b1 2025-05-30 xs }
375 f83445b1 2025-05-30 xs
376 f83445b1 2025-05-30 xs alias ssh-ids=ssh_ids
377 f83445b1 2025-05-30 xs ssh_ids() {
378 f83445b1 2025-05-30 xs ssh_users | grep -v ^- | sort -u
379 f83445b1 2025-05-30 xs }
380 f83445b1 2025-05-30 xs
381 f83445b1 2025-05-30 xs alias ssh-authorized-keys=ssh_authorized_keys
382 f83445b1 2025-05-30 xs alias ssh-auth=ssh_authorized_keys
383 f83445b1 2025-05-30 xs ssh_authorized_keys() {
384 f83445b1 2025-05-30 xs ssh_users | grep -e ^- | sed -e 's/^- /nodes\//' -e 's/:$//'
385 f83445b1 2025-05-30 xs }
386 f83445b1 2025-05-30 xs
387 f83445b1 2025-05-30 xs alias ssh-ids-hosts=ssh_ids_hosts
388 f83445b1 2025-05-30 xs # shellcheck disable=SC2046
389 f83445b1 2025-05-30 xs ssh_ids_hosts() {
390 f83445b1 2025-05-30 xs ssh_ids | awk '{ print $3 }' |
391 f83445b1 2025-05-30 xs while read -r id; do
392 f83445b1 2025-05-30 xs grep -e "$id" $(ssh_authorized_keys)
393 f83445b1 2025-05-30 xs done | while IFS="$IFS/:" read -r _ hostname _ keyfile _ _ comment; do
394 f83445b1 2025-05-30 xs printf '"%s" -> "%s" -> "%s"\n' "${comment#* }" "${keyfile#authorized_keys_}" "$hostname"
395 f83445b1 2025-05-30 xs done | sort
396 f83445b1 2025-05-30 xs }
397 f83445b1 2025-05-30 xs
398 03d8f521 2025-05-27 xs unlock() {
399 03d8f521 2025-05-27 xs eval "$(ssh-agent)"
400 03d8f521 2025-05-27 xs ssh-add "$SSH_IDENTITY_FILE"
401 03d8f521 2025-05-27 xs }
402 03d8f521 2025-05-27 xs
403 03d8f521 2025-05-27 xs copy() (
404 87bce7c5 2025-05-30 xs test "$R7_DRYRUN" = yes && return 0
405 46924c01 2025-05-28 xs _debug "COPY $1 $2 BEGIN"
406 03d8f521 2025-05-27 xs node=${2%%:*}
407 03d8f521 2025-05-27 xs dir=${2##*:}
408 03d8f521 2025-05-27 xs if r=$(ssh "$node" command -v openrsync); then
409 03d8f521 2025-05-27 xs if openrsync -V 2>/dev/null; then
410 46924c01 2025-05-28 xs _debug "COPY $1 $2 USE OPENRSYNC"
411 03d8f521 2025-05-27 xs openrsync -e "/usr/bin/ssh -oConnectTimeout=$SSH_CONNECT_TIMEOUT -F $SSH_CONFIG_FILE" \
412 03d8f521 2025-05-27 xs --rsync-path="$r" \
413 03d8f521 2025-05-27 xs --delete \
414 03d8f521 2025-05-27 xs -a "$1" "$2" && return 0
415 03d8f521 2025-05-27 xs fi
416 03d8f521 2025-05-27 xs fi
417 03d8f521 2025-05-27 xs if r=$(ssh "$node" command -v rsync); then
418 03d8f521 2025-05-27 xs if rsync -V 1>/dev/null; then
419 46924c01 2025-05-28 xs _debug "COPY $1 $2 USE RSYNC"
420 03d8f521 2025-05-27 xs rsync -e "/usr/bin/ssh -oConnectTimeout=$SSH_CONNECT_TIMEOUT -F $SSH_CONFIG_FILE" \
421 03d8f521 2025-05-27 xs --rsync-path="$r" \
422 03d8f521 2025-05-27 xs --delete \
423 03d8f521 2025-05-27 xs -aq "$1" "$2" && return 0
424 03d8f521 2025-05-27 xs fi
425 03d8f521 2025-05-27 xs fi
426 46924c01 2025-05-28 xs _debug "COPY $1 $2 USE SCP"
427 03d8f521 2025-05-27 xs dir=${dir:-/tmp/r7}
428 03d8f521 2025-05-27 xs ssh "$node" rm -fr "$dir/$1" 2>/dev/null
429 8e44e3d4 2025-06-25 xs scp "-oConnectTimeout=$SSH_CONNECT_TIMEOUT" -qF "$SSH_CONFIG_FILE" -r "$1" "$2" && return 0
430 8e44e3d4 2025-06-25 xs _fail "Unable to copy '$1' to '$2'."
431 03d8f521 2025-05-27 xs )
432 03d8f521 2025-05-27 xs
433 03d8f521 2025-05-27 xs # Deployment functions
434 03d8f521 2025-05-27 xs # ====================
435 03d8f521 2025-05-27 xs
436 46924c01 2025-05-28 xs _trace_id_new() { date +%s; }
437 03d8f521 2025-05-27 xs
438 03d8f521 2025-05-27 xs nodes() (
439 46924c01 2025-05-28 xs cd "$R7_WORKDIR" || return 2
440 0253bef1 2025-05-29 xs test -d ./nodes || return 0
441 03d8f521 2025-05-27 xs find nodes -type d -maxdepth 1 | tail -n +2 | awk -F/ '{ print $2 }'
442 03d8f521 2025-05-27 xs )
443 03d8f521 2025-05-27 xs
444 46924c01 2025-05-28 xs alias nodes-active=nodes_active
445 46924c01 2025-05-28 xs alias nodesact=nodes_active
446 03d8f521 2025-05-27 xs nodes_active() (
447 f83445b1 2025-05-30 xs test "$R7_DRYRUN" = yes && {
448 f83445b1 2025-05-30 xs nodes
449 f83445b1 2025-05-30 xs return 0
450 f83445b1 2025-05-30 xs }
451 46924c01 2025-05-28 xs if test -s "$R7_WORKDIR/.active_nodes"; then
452 46924c01 2025-05-28 xs cat "$R7_WORKDIR/.active_nodes"
453 03d8f521 2025-05-27 xs else
454 46924c01 2025-05-28 xs touch "$R7_WORKDIR/.active_nodes"
455 03d8f521 2025-05-27 xs for node in $(nodes); do
456 46924c01 2025-05-28 xs _debug "ACTIVE $node"
457 03d8f521 2025-05-27 xs if ssh "$node" :; then
458 46924c01 2025-05-28 xs printf "%s\\n" "$node" >>"$R7_WORKDIR/.active_nodes"
459 03d8f521 2025-05-27 xs fi
460 03d8f521 2025-05-27 xs done
461 46924c01 2025-05-28 xs cat "$R7_WORKDIR/.active_nodes"
462 03d8f521 2025-05-27 xs fi
463 03d8f521 2025-05-27 xs )
464 03d8f521 2025-05-27 xs
465 46924c01 2025-05-28 xs alias run-config=run_config
466 46924c01 2025-05-28 xs alias rc=run_config
467 46924c01 2025-05-28 xs # shellcheck disable=SC1090,SC2031
468 03d8f521 2025-05-27 xs run_config() {
469 46924c01 2025-05-28 xs trace_id=$(_trace_id_new)
470 03d8f521 2025-05-27 xs # shellcheck disable=SC1091
471 46924c01 2025-05-28 xs _debug LOADING "$R7_SITE_CONFIG"
472 f6bdfddc 2025-06-03 xs sh -n "$R7_SITE_CONFIG" && . "$R7_SITE_CONFIG"
473 03d8f521 2025-05-27 xs }
474 03d8f521 2025-05-27 xs
475 03d8f521 2025-05-27 xs # Inherits $target from group()
476 03d8f521 2025-05-27 xs # shellcheck disable=SC2031
477 46924c01 2025-05-28 xs _deploy() (
478 46924c01 2025-05-28 xs _debug "DEPLOY $new_name $target"
479 46924c01 2025-05-28 xs cd "$R7_WORKDIR" || exit 2
480 03d8f521 2025-05-27 xs stem="groups/$new_name"
481 03d8f521 2025-05-27 xs nodedir="nodes/$target"
482 0253bef1 2025-05-29 xs test "$R7_DRYRUN" = yes || {
483 0253bef1 2025-05-29 xs if test -d "$stem.dir"; then
484 8e44e3d4 2025-06-25 xs ssh "$target" /bin/sh -c 'umask 027; mkdir -p /tmp/r7'
485 03d8f521 2025-05-27 xs copy "$stem.dir" "$target:/tmp/r7" || return 3
486 0253bef1 2025-05-29 xs fi
487 0253bef1 2025-05-29 xs if test -d "$nodedir"; then
488 03d8f521 2025-05-27 xs test -f /tmp/r7/"$trace_id.$target" || {
489 8e44e3d4 2025-06-25 xs ssh "$target" /bin/sh -c 'umask 027; mkdir -p /tmp/r7'
490 03d8f521 2025-05-27 xs copy "$nodedir" "$target:/tmp/r7" || return 3
491 03d8f521 2025-05-27 xs }
492 0253bef1 2025-05-29 xs fi
493 0253bef1 2025-05-29 xs }
494 03d8f521 2025-05-27 xs if test -f "$stem"; then
495 0253bef1 2025-05-29 xs if _payload "$stem" | sh -n; then
496 0253bef1 2025-05-29 xs _debug SYNTAX OK "$stem"
497 0253bef1 2025-05-29 xs test "$R7_DRYRUN" = yes || {
498 0253bef1 2025-05-29 xs _payload "$stem" | ssh 2>&1 "$target" /bin/sh - |
499 0253bef1 2025-05-29 xs _collect "$R7_RUNDIR/$trace_id.$target.$new_name"
500 0253bef1 2025-05-29 xs }
501 0253bef1 2025-05-29 xs else
502 0253bef1 2025-05-29 xs _debug SYNTAX KO "$stem"
503 0253bef1 2025-05-29 xs echo 1>&2 "syntax error in '$stem', skipping..."
504 0253bef1 2025-05-29 xs return 3
505 0253bef1 2025-05-29 xs fi
506 03d8f521 2025-05-27 xs fi
507 03d8f521 2025-05-27 xs )
508 03d8f521 2025-05-27 xs
509 03d8f521 2025-05-27 xs members() (
510 03d8f521 2025-05-27 xs set -f -- $(printf -- "-e %s " "$@")
511 03d8f521 2025-05-27 xs nodes_active | grep "$@"
512 03d8f521 2025-05-27 xs )
513 03d8f521 2025-05-27 xs
514 0253bef1 2025-05-29 xs # shellcheck disable=SC2030
515 03d8f521 2025-05-27 xs group() (
516 46924c01 2025-05-28 xs test $# -eq 0 && return 0
517 46924c01 2025-05-28 xs cd "$R7_WORKDIR" || return 2
518 03d8f521 2025-05-27 xs umask 027
519 0253bef1 2025-05-29 xs test "$R7_DRYRUN" = yes || {
520 0253bef1 2025-05-29 xs mkdir -p "$R7_RUNDIR" || return 2
521 0253bef1 2025-05-29 xs cd "$R7_RUNDIR" || return 2
522 0253bef1 2025-05-29 xs }
523 46924c01 2025-05-28 xs _debug "CREATED $R7_RUNDIR"
524 03d8f521 2025-05-27 xs new_name=$1
525 46924c01 2025-05-28 xs _debug "PROCESSING GROUP $new_name"
526 03d8f521 2025-05-27 xs shift
527 03d8f521 2025-05-27 xs # shellcheck disable=SC2046
528 0253bef1 2025-05-29 xs set -fm
529 03d8f521 2025-05-27 xs for target in $(members "$@"); do
530 46924c01 2025-05-28 xs case $R7_PARALLEL in
531 03d8f521 2025-05-27 xs yes)
532 46924c01 2025-05-28 xs _deploy &
533 03d8f521 2025-05-27 xs ;;
534 03d8f521 2025-05-27 xs *)
535 46924c01 2025-05-28 xs _deploy
536 03d8f521 2025-05-27 xs ;;
537 03d8f521 2025-05-27 xs esac
538 03d8f521 2025-05-27 xs done
539 03d8f521 2025-05-27 xs wait
540 03d8f521 2025-05-27 xs )
541 03d8f521 2025-05-27 xs
542 0253bef1 2025-05-29 xs group_prefixes() (
543 0253bef1 2025-05-29 xs grep 2>/dev/null -e "^.*()" "$R7_WORKDIR/groups/$1" | cut -d\( -f1 | cut -d_ -f1 | uniq
544 0253bef1 2025-05-29 xs )
545 0253bef1 2025-05-29 xs
546 46924c01 2025-05-28 xs alias group-functions=group_functions
547 46924c01 2025-05-28 xs alias groupfuncs=group_functions
548 46924c01 2025-05-28 xs group_functions() (
549 0253bef1 2025-05-29 xs if test "$R7_GROUP_ALLPREFIX" = yes; then
550 8fe13599 2025-06-05 xs grep 2>/dev/null -e "^[^#].*()" "$R7_WORKDIR/groups/$1" | cut -d\( -f1
551 0253bef1 2025-05-29 xs return 0
552 0253bef1 2025-05-29 xs fi
553 03d8f521 2025-05-27 xs for pre in $prefix; do
554 2ae3e68f 2025-06-07 xs grep 2>/dev/null -e "^${pre}.*()" "$R7_WORKDIR/groups/$1" | cut -d\( -f1
555 03d8f521 2025-05-27 xs done
556 03d8f521 2025-05-27 xs )
557 03d8f521 2025-05-27 xs
558 8fe13599 2025-06-05 xs alias group-functions-all=group_functions_all
559 8fe13599 2025-06-05 xs alias groupfuncsall=group_functions_all
560 8fe13599 2025-06-05 xs group_functions_all() (
561 8fe13599 2025-06-05 xs set -- $(cd "$R7_WORKDIR/groups" && find ./* -type f -maxdepth 0)
562 8fe13599 2025-06-05 xs for file; do
563 8fe13599 2025-06-05 xs group_functions "${file##./}" | while read -r func; do
564 8fe13599 2025-06-05 xs printf %s::%s\\n "${file##./}" "$func"
565 8fe13599 2025-06-05 xs done
566 8fe13599 2025-06-05 xs done
567 8fe13599 2025-06-05 xs )
568 8fe13599 2025-06-05 xs
569 46924c01 2025-05-28 xs prefix() {
570 46924c01 2025-05-28 xs prefix="$*"
571 730e151b 2025-06-02 xs R7_PREFIX=$prefix
572 730e151b 2025-06-02 xs export prefix R7_PREFIX
573 46924c01 2025-05-28 xs }
574 46924c01 2025-05-28 xs
575 46924c01 2025-05-28 xs _call() (
576 46924c01 2025-05-28 xs cd "$R7_WORKDIR" || return 2
577 2ae3e68f 2025-06-07 xs grep -e "^$2.*()" "$1" |
578 03d8f521 2025-05-27 xs cut -d\( -f1 | while read -r function; do
579 46924c01 2025-05-28 xs _debug "CALL $1 $function"
580 03d8f521 2025-05-27 xs echo trace "${1#*/}" "$function" START
581 03d8f521 2025-05-27 xs echo "_ret=; $function || { _ret=\$?; : ;}"
582 03d8f521 2025-05-27 xs echo trace "${1#*/}" "$function" END "\${_ret:-0}"
583 f83445b1 2025-05-30 xs test "$R7_DRYRUN" = yes && {
584 f83445b1 2025-05-30 xs echo 1>&2 "- (dryrun) $target:$new_name::$function"
585 f83445b1 2025-05-30 xs }
586 03d8f521 2025-05-27 xs done
587 03d8f521 2025-05-27 xs )
588 03d8f521 2025-05-27 xs
589 46924c01 2025-05-28 xs _payload() (
590 8e44e3d4 2025-06-25 xs echo "hostname=$target"
591 03d8f521 2025-05-27 xs echo "trace_id=$trace_id"
592 0253bef1 2025-05-29 xs echo "groupname=$new_name"
593 730e151b 2025-06-02 xs echo "exitonerror=$R7_GROUP_EXITONERROR"
594 03d8f521 2025-05-27 xs cat <<-'eof'
595 03d8f521 2025-05-27 xs trace() {
596 03d8f521 2025-05-27 xs echo ":: $trace_id $(nodename) $*" 1>&2
597 03d8f521 2025-05-27 xs }
598 03d8f521 2025-05-27 xs error() {
599 730e151b 2025-06-02 xs _ret=$?
600 46924c01 2025-05-28 xs trace ERROR "$*" 1>&2
601 730e151b 2025-06-02 xs test "$exitonerror" = yes && {
602 730e151b 2025-06-02 xs case $_ret in (0) _ret=1 ;; esac
603 730e151b 2025-06-02 xs trace EXIT $_ret
604 730e151b 2025-06-02 xs exit $_ret
605 730e151b 2025-06-02 xs }
606 03d8f521 2025-05-27 xs }
607 46924c01 2025-05-28 xs nodename() (
608 46924c01 2025-05-28 xs hostname=${hostname:-$(uname -n)}
609 03d8f521 2025-05-27 xs echo "${hostname%%.*}"
610 46924c01 2025-05-28 xs )
611 46924c01 2025-05-28 xs node() (
612 03d8f521 2025-05-27 xs atom=/tmp/r7/$(nodename)/$1
613 b7a0ae1e 2025-05-27 xs test -f "$atom" && return 0
614 b7a0ae1e 2025-05-27 xs test -d "$atom" && return 0
615 03d8f521 2025-05-27 xs return 31
616 46924c01 2025-05-28 xs )
617 03d8f521 2025-05-27 xs nodedir() {
618 03d8f521 2025-05-27 xs echo "/tmp/r7/$(nodename)"
619 03d8f521 2025-05-27 xs }
620 0253bef1 2025-05-29 xs groupdir() (
621 0253bef1 2025-05-29 xs echo "/tmp/r7/$groupname.dir"
622 0253bef1 2025-05-29 xs )
623 8e44e3d4 2025-06-25 xs _source() {
624 730e151b 2025-06-02 xs if sh -n "$1"; then
625 730e151b 2025-06-02 xs trace SOURCE "$1"
626 730e151b 2025-06-02 xs . "$1"
627 730e151b 2025-06-02 xs else
628 730e151b 2025-06-02 xs trace SOURCE FAILED "$1"
629 730e151b 2025-06-02 xs return 2
630 730e151b 2025-06-02 xs fi
631 730e151b 2025-06-02 xs }
632 8e44e3d4 2025-06-25 xs fsource() {
633 8e44e3d4 2025-06-25 xs test $# -gt 0 || {
634 8e44e3d4 2025-06-25 xs error missing source argument
635 8e44e3d4 2025-06-25 xs return 2
636 8e44e3d4 2025-06-25 xs }
637 8e44e3d4 2025-06-25 xs _source "$(test -f "$1" && printf %s "$PWD/${1##"$PWD"}")"
638 8e44e3d4 2025-06-25 xs }
639 8e44e3d4 2025-06-25 xs nodesource() {
640 8e44e3d4 2025-06-25 xs node "$1" && cd "$(nodedir)" && fsource "$1"
641 8e44e3d4 2025-06-25 xs }
642 8e44e3d4 2025-06-25 xs groupsource() {
643 8e44e3d4 2025-06-25 xs cd "$(groupdir)" && _fsource "$1"
644 8e44e3d4 2025-06-25 xs }
645 87bce7c5 2025-05-30 xs install() ( cd /tmp/r7 && r7_install "$@" ; )
646 87bce7c5 2025-05-30 xs groupinstall() ( cd "$(groupdir)" && r7_install "$@" ; )
647 87bce7c5 2025-05-30 xs nodeinstall() ( cd "$(nodedir)" && r7_install "$@" ; )
648 730e151b 2025-06-02 xs _getperm() {
649 730e151b 2025-06-02 xs test -f "$1" && {
650 730e151b 2025-06-02 xs ls -l "$1" | grep -v total | awk '{ print $1 " " $3 " " $4 }'
651 730e151b 2025-06-02 xs }
652 730e151b 2025-06-02 xs }
653 730e151b 2025-06-02 xs _setperm() {
654 730e151b 2025-06-02 xs before=$(_getperm "$1")
655 730e151b 2025-06-02 xs if test -n "$owner"; then
656 730e151b 2025-06-02 xs chown "$owner" "$1" || {
657 730e151b 2025-06-02 xs error chown "$1"
658 730e151b 2025-06-02 xs return 2
659 730e151b 2025-06-02 xs }
660 730e151b 2025-06-02 xs fi
661 730e151b 2025-06-02 xs if test -n "$mode"; then
662 730e151b 2025-06-02 xs chmod "$mode" "$1" || {
663 730e151b 2025-06-02 xs error chmod "$1"
664 730e151b 2025-06-02 xs return 2
665 730e151b 2025-06-02 xs }
666 730e151b 2025-06-02 xs fi
667 730e151b 2025-06-02 xs after=$(_getperm "$1")
668 730e151b 2025-06-02 xs if test "$before" != "$after"; then
669 730e151b 2025-06-02 xs trace PERMISSIONS CHANGE "$before" TO "$after" ON "$1"
670 730e151b 2025-06-02 xs fi
671 730e151b 2025-06-02 xs }
672 730e151b 2025-06-02 xs _install() {
673 730e151b 2025-06-02 xs test -e "$2" && {
674 730e151b 2025-06-02 xs trace DIFF
675 730e151b 2025-06-02 xs diff -U2 "$2" "$1"
676 730e151b 2025-06-02 xs }
677 730e151b 2025-06-02 xs cp "$1" "$2" ||
678 730e151b 2025-06-02 xs { error copying "$source" to "$2"; return 2 ; }
679 730e151b 2025-06-02 xs _setperm "$2"
680 730e151b 2025-06-02 xs return 0
681 730e151b 2025-06-02 xs }
682 0253bef1 2025-05-29 xs r7_install() (
683 03d8f521 2025-05-27 xs while getopts "o:m:" arg; do
684 03d8f521 2025-05-27 xs case $arg in
685 730e151b 2025-06-02 xs o) owner=$OPTARG ;;
686 730e151b 2025-06-02 xs m) mode=$OPTARG ;;
687 f6bdfddc 2025-06-03 xs *) : ;;
688 03d8f521 2025-05-27 xs esac
689 03d8f521 2025-05-27 xs done
690 46924c01 2025-05-28 xs shift $((OPTIND - 1))
691 03d8f521 2025-05-27 xs source=$1
692 03d8f521 2025-05-27 xs target=$2
693 b7a0ae1e 2025-05-27 xs source_dirname=${1%/*}
694 730e151b 2025-06-02 xs if ! test -e "$source"; then
695 46924c01 2025-05-28 xs error "$source" not found
696 46924c01 2025-05-28 xs return 2
697 46924c01 2025-05-28 xs fi
698 730e151b 2025-06-02 xs case $target in
699 730e151b 2025-06-02 xs */) test -d "$target" || {
700 730e151b 2025-06-02 xs error "$target" directory not found
701 730e151b 2025-06-02 xs return 2
702 730e151b 2025-06-02 xs } ;;
703 730e151b 2025-06-02 xs esac
704 730e151b 2025-06-02 xs if test -e "$target"; then
705 730e151b 2025-06-02 xs cmp -s "$source" "$target"
706 730e151b 2025-06-02 xs ret=$?
707 730e151b 2025-06-02 xs destination_is=file
708 730e151b 2025-06-02 xs fi
709 46924c01 2025-05-28 xs if test -d "$target"; then
710 46924c01 2025-05-28 xs new_filename="$target/${source##$source_dirname/}"
711 46924c01 2025-05-28 xs cmp -s "$source" "$new_filename"
712 46924c01 2025-05-28 xs ret=$?
713 730e151b 2025-06-02 xs destination_is=directory
714 46924c01 2025-05-28 xs fi
715 730e151b 2025-06-02 xs if test -e "$source"; then
716 730e151b 2025-06-02 xs if test -d "$target"; then
717 730e151b 2025-06-02 xs destination_is=directory
718 730e151b 2025-06-02 xs else
719 730e151b 2025-06-02 xs destination_is=file
720 03d8f521 2025-05-27 xs fi
721 46924c01 2025-05-28 xs fi
722 46924c01 2025-05-28 xs case "$ret" in
723 46924c01 2025-05-28 xs 0) return 30 ;;
724 730e151b 2025-06-02 xs *)
725 730e151b 2025-06-02 xs case $destination_is in
726 730e151b 2025-06-02 xs directory)
727 730e151b 2025-06-02 xs new_filename="$target/${source##$source_dirname/}"
728 730e151b 2025-06-02 xs _install "$source" "$new_filename"
729 730e151b 2025-06-02 xs ;;
730 730e151b 2025-06-02 xs file)
731 730e151b 2025-06-02 xs _install "$source" "$target"
732 730e151b 2025-06-02 xs ;;
733 730e151b 2025-06-02 xs esac
734 730e151b 2025-06-02 xs ;;
735 03d8f521 2025-05-27 xs esac
736 46924c01 2025-05-28 xs )
737 b6cef3b8 2025-06-04 xs installdir() { r7_installdir "$@" ; }
738 f6bdfddc 2025-06-03 xs groupinstalldir() ( cd "$(groupdir)" && r7_installdir "$@" ; )
739 f6bdfddc 2025-06-03 xs nodeinstalldir() ( cd "$(nodedir)" && r7_installdir "$@" ; )
740 730e151b 2025-06-02 xs r7_installdir() (
741 f6bdfddc 2025-06-03 xs while getopts "o:m:O:M:" arg; do
742 730e151b 2025-06-02 xs case $arg in
743 730e151b 2025-06-02 xs o) fileowner=$OPTARG ;;
744 730e151b 2025-06-02 xs m) filenode=$OPTARG ;;
745 730e151b 2025-06-02 xs O) dirowner=$OPTARG ;;
746 730e151b 2025-06-02 xs M) dirmode=$OPTARG ;;
747 f6bdfddc 2025-06-03 xs *) : ;;
748 730e151b 2025-06-02 xs esac
749 730e151b 2025-06-02 xs done
750 f6bdfddc 2025-06-03 xs shift $((OPTIND - 1))
751 f6bdfddc 2025-06-03 xs source=$1
752 f6bdfddc 2025-06-03 xs target=$2
753 f6bdfddc 2025-06-03 xs source_basename=${source##*/}
754 f6bdfddc 2025-06-03 xs source_dirname=$PWD/${source%%/*}
755 f6bdfddc 2025-06-03 xs target_basename=${target##*/}
756 f6bdfddc 2025-06-03 xs test -d "$source" || {
757 f6bdfddc 2025-06-03 xs error "$source" directory not found
758 f6bdfddc 2025-06-03 xs return 2
759 f6bdfddc 2025-06-03 xs }
760 f6bdfddc 2025-06-03 xs for dir in $(find "$source" -type d); do
761 f6bdfddc 2025-06-03 xs newdir=${dir#./}
762 f6bdfddc 2025-06-03 xs (
763 f6bdfddc 2025-06-03 xs cd "$target" || return 2
764 f6bdfddc 2025-06-03 xs mkdir -p "$newdir" || { error unable to create "$newdir"; return 2 ; }
765 f6bdfddc 2025-06-03 xs owner=$dirowner mode=$dirmode _setperm "$1"
766 f6bdfddc 2025-06-03 xs )
767 f6bdfddc 2025-06-03 xs done
768 f6bdfddc 2025-06-03 xs for file in $(find "$source" -type f); do
769 f6bdfddc 2025-06-03 xs newfile=${file#./}
770 f6bdfddc 2025-06-03 xs r7_install -o "$fileowner" -m "$filemode" "$file" "$target/$newfile"
771 f6bdfddc 2025-06-03 xs done
772 730e151b 2025-06-02 xs )
773 6e564797 2025-06-06 xs template() (
774 6e564797 2025-06-06 xs while getopts "s:" arg; do
775 6e564797 2025-06-06 xs case $arg in
776 6e564797 2025-06-06 xs s) source=$OPTARG ;;
777 6e564797 2025-06-06 xs *) : ;;
778 6e564797 2025-06-06 xs esac
779 6e564797 2025-06-06 xs done
780 6e564797 2025-06-06 xs shift $((OPTIND - 1))
781 6e564797 2025-06-06 xs set -a
782 8e44e3d4 2025-06-25 xs test -n "$source" && sh -n "$source" && set -a && . "./$source" && set +a
783 6e564797 2025-06-06 xs for file; do
784 6e564797 2025-06-06 xs sh > "${file%%.tpl}" <<-.
785 6e564797 2025-06-06 xs cat <<-..
786 6e564797 2025-06-06 xs $(cat "$file")
787 6e564797 2025-06-06 xs ..
788 6e564797 2025-06-06 xs .
789 6e564797 2025-06-06 xs done
790 6e564797 2025-06-06 xs )
791 6e564797 2025-06-06 xs grouptemplate() ( cd "$(groupdir)" && template "$@" ; )
792 6e564797 2025-06-06 xs nodetemplate() ( cd "$(nodedir)" && template "$@" ; )
793 730e151b 2025-06-02 xs set -e
794 730e151b 2025-06-02 xs cd /tmp/r7 && umask 027
795 730e151b 2025-06-02 xs set +e
796 730e151b 2025-06-02 xs nodename=$(nodename)
797 730e151b 2025-06-02 xs nodedir=$(nodedir)
798 730e151b 2025-06-02 xs groupdir=$(groupdir)
799 03d8f521 2025-05-27 xs trace CONNECTED $(date +%s)
800 8e44e3d4 2025-06-25 xs exec 1>&2
801 03d8f521 2025-05-27 xs eof
802 03d8f521 2025-05-27 xs cat "$1"
803 730e151b 2025-06-02 xs _debug "PREFIX $R7_PREFIX"
804 730e151b 2025-06-02 xs for run in $R7_PREFIX; do
805 46924c01 2025-05-28 xs _call "$1" "$run"
806 03d8f521 2025-05-27 xs done
807 03d8f521 2025-05-27 xs cat <<-'eof'
808 03d8f521 2025-05-27 xs trace DISCONNECT $(date +%s)
809 03d8f521 2025-05-27 xs eof
810 03d8f521 2025-05-27 xs )
811 03d8f521 2025-05-27 xs
812 03d8f521 2025-05-27 xs # Interactive output function
813 03d8f521 2025-05-27 xs # ===========================
814 03d8f521 2025-05-27 xs
815 46924c01 2025-05-28 xs # shellcheck disable=SC2086,SC2030
816 46924c01 2025-05-28 xs _collect() (
817 8e44e3d4 2025-06-25 xs set +u
818 03d8f521 2025-05-27 xs tee -a "$1" | while read -r line; do
819 03d8f521 2025-05-27 xs set -- $line
820 03d8f521 2025-05-27 xs case $line in
821 03d8f521 2025-05-27 xs ::*)
822 46924c01 2025-05-28 xs # Traces from payload
823 03d8f521 2025-05-27 xs trace_id=$2
824 03d8f521 2025-05-27 xs host=$3
825 03d8f521 2025-05-27 xs group=$4
826 03d8f521 2025-05-27 xs function=$5
827 03d8f521 2025-05-27 xs status=$6
828 03d8f521 2025-05-27 xs endcode=$7
829 688c9bfd 2025-06-03 xs # Traces from _call
830 03d8f521 2025-05-27 xs case $status in
831 03d8f521 2025-05-27 xs START)
832 46924c01 2025-05-28 xs save_group=$group save_function=$function
833 03d8f521 2025-05-27 xs in_function=1
834 46924c01 2025-05-28 xs if test "$R7_SHOWOUTPUT" = yes; then
835 03d8f521 2025-05-27 xs echo "- (output) $host:$group::$function"
836 03d8f521 2025-05-27 xs fi
837 03d8f521 2025-05-27 xs continue
838 03d8f521 2025-05-27 xs ;;
839 03d8f521 2025-05-27 xs END)
840 03d8f521 2025-05-27 xs in_function=0
841 03d8f521 2025-05-27 xs case $endcode in
842 730e151b 2025-06-02 xs 0 | 30 | 31) echo "- (ok) $host:$group::$function" ;;
843 03d8f521 2025-05-27 xs *) echo "! (error $endcode) $host:$group::$function" ;;
844 03d8f521 2025-05-27 xs esac
845 03d8f521 2025-05-27 xs ;;
846 03d8f521 2025-05-27 xs esac
847 46924c01 2025-05-28 xs # Traces from functions
848 46924c01 2025-05-28 xs case $2 in
849 46924c01 2025-05-28 xs "$trace_id")
850 46924c01 2025-05-28 xs case $4 in
851 730e151b 2025-06-02 xs SOURCE) echo "+ (source) $host:$save_group::$save_function" ;;
852 46924c01 2025-05-28 xs DIFF) echo "+ (diff) $host:$save_group::$save_function" ;;
853 46924c01 2025-05-28 xs PERMISSIONS) echo "+ (permissions) $host:$save_group::$save_function" ;;
854 46924c01 2025-05-28 xs ERROR) echo "! (error) $host:$save_group::$save_function" ;;
855 730e151b 2025-06-02 xs EXIT) echo "! (exit) $host:$save_group::$save_function" ;;
856 46924c01 2025-05-28 xs esac
857 46924c01 2025-05-28 xs ;;
858 46924c01 2025-05-28 xs esac
859 03d8f521 2025-05-27 xs ;;
860 03d8f521 2025-05-27 xs esac
861 46924c01 2025-05-28 xs
862 46924c01 2025-05-28 xs if test "$R7_SHOWOUTPUT" = yes; then
863 03d8f521 2025-05-27 xs test "$in_function" -eq 1 &&
864 03d8f521 2025-05-27 xs printf "%s\\n" "$line"
865 03d8f521 2025-05-27 xs fi
866 03d8f521 2025-05-27 xs done
867 03d8f521 2025-05-27 xs )
868 03d8f521 2025-05-27 xs
869 03d8f521 2025-05-27 xs # Text output functions
870 03d8f521 2025-05-27 xs # =====================
871 03d8f521 2025-05-27 xs
872 46924c01 2025-05-28 xs alias output-dump=output_dump
873 46924c01 2025-05-28 xs alias outdump=output_dump
874 03d8f521 2025-05-27 xs output_dump() (
875 03d8f521 2025-05-27 xs set -e -- $(output_latest)
876 46924c01 2025-05-28 xs test $# -eq 0 && return 0
877 0253bef1 2025-05-29 xs cd "$R7_WORKDIR" || _fail "Unable to cd to workdir: $R7_WORKDIR"
878 0253bef1 2025-05-29 xs test "$R7_DRYRUN" = yes || {
879 0253bef1 2025-05-29 xs mkdir -p "$R7_OUTPUTDIR"
880 0253bef1 2025-05-29 xs awk -voutput_dir="$R7_OUTPUTDIR" '
881 03d8f521 2025-05-27 xs BEGIN {
882 03d8f521 2025-05-27 xs trace_id=""
883 03d8f521 2025-05-27 xs hostname=""
884 03d8f521 2025-05-27 xs funcname=""
885 03d8f521 2025-05-27 xs groupname=""
886 03d8f521 2025-05-27 xs in_function_block=0
887 03d8f521 2025-05-27 xs }
888 03d8f521 2025-05-27 xs /^:: [0-9].*/ {
889 03d8f521 2025-05-27 xs if ($4 == "CONNECTED") {
890 03d8f521 2025-05-27 xs trace_id=$2
891 03d8f521 2025-05-27 xs hostname=$3
892 03d8f521 2025-05-27 xs timestamp_connect=$5
893 03d8f521 2025-05-27 xs system("mkdir -p " output_dir "/" hostname)
894 03d8f521 2025-05-27 xs }
895 03d8f521 2025-05-27 xs }
896 03d8f521 2025-05-27 xs $2 == trace_id && $6 == "START" {
897 03d8f521 2025-05-27 xs groupname=$4
898 03d8f521 2025-05-27 xs funcname=$5
899 03d8f521 2025-05-27 xs in_function_block=1
900 03d8f521 2025-05-27 xs output_node = output_dir "/" hostname "/" groupname "/" funcname
901 03d8f521 2025-05-27 xs output_status = output_node "/status"
902 03d8f521 2025-05-27 xs output_output = output_node "/output"
903 03d8f521 2025-05-27 xs system("rm -fr " output_node)
904 03d8f521 2025-05-27 xs system("mkdir -p " output_node)
905 03d8f521 2025-05-27 xs next
906 03d8f521 2025-05-27 xs }
907 730e151b 2025-06-02 xs $2 == trace_id && $4 == "EXIT" {
908 730e151b 2025-06-02 xs in_function_block=0
909 730e151b 2025-06-02 xs system("echo " $5 " >" output_status)
910 730e151b 2025-06-02 xs }
911 03d8f521 2025-05-27 xs $2 == trace_id && $6 == "END" {
912 03d8f521 2025-05-27 xs in_function_block=0
913 03d8f521 2025-05-27 xs system("echo " $7 " >" output_status)
914 03d8f521 2025-05-27 xs }
915 03d8f521 2025-05-27 xs in_function_block == 1 {
916 03d8f521 2025-05-27 xs print > output_output
917 03d8f521 2025-05-27 xs }
918 03d8f521 2025-05-27 xs $2 == trace_id && $4 == "DISCONNECT" {
919 03d8f521 2025-05-27 xs timestamp_disconnect=$5
920 03d8f521 2025-05-27 xs difference=timestamp_disconnect - timestamp_connect
921 03d8f521 2025-05-27 xs output_duration = output_dir "/" hostname "/" groupname "/duration"
922 03d8f521 2025-05-27 xs system("echo " difference " >" output_duration)
923 03d8f521 2025-05-27 xs }
924 03d8f521 2025-05-27 xs ' "$@"
925 0253bef1 2025-05-29 xs }
926 03d8f521 2025-05-27 xs )
927 03d8f521 2025-05-27 xs
928 f6bdfddc 2025-06-03 xs _epoch() (
929 f6bdfddc 2025-06-03 xs case $(uname) in
930 f6bdfddc 2025-06-03 xs OpenBSD | FreeBSD | NetBSD | Darwin)
931 f6bdfddc 2025-06-03 xs date -r "$1"
932 f6bdfddc 2025-06-03 xs ;;
933 f6bdfddc 2025-06-03 xs Linux)
934 f6bdfddc 2025-06-03 xs date -d "@$1"
935 f6bdfddc 2025-06-03 xs ;;
936 f6bdfddc 2025-06-03 xs *)
937 f6bdfddc 2025-06-03 xs perl -e "print scalar localtime($1)"
938 f6bdfddc 2025-06-03 xs ;;
939 f6bdfddc 2025-06-03 xs esac
940 f6bdfddc 2025-06-03 xs
941 f6bdfddc 2025-06-03 xs )
942 f6bdfddc 2025-06-03 xs
943 46924c01 2025-05-28 xs alias output-latest=output_latest
944 46924c01 2025-05-28 xs alias outlatest=output_latest
945 46924c01 2025-05-28 xs output_latest() (
946 46924c01 2025-05-28 xs set -e
947 03d8f521 2025-05-27 xs latest=$(
948 03d8f521 2025-05-27 xs # shellcheck disable=SC2012
949 31e019a2 2025-05-31 xs ls 2>/dev/null -lt1 "$R7_RUNDIR/" | while read -r file; do
950 03d8f521 2025-05-27 xs echo "${file%%.*}"
951 03d8f521 2025-05-27 xs break
952 03d8f521 2025-05-27 xs done
953 03d8f521 2025-05-27 xs )
954 46924c01 2025-05-28 xs test -z "$latest" && return 0
955 f6bdfddc 2025-06-03 xs latest_date=$(_epoch "$latest")
956 03d8f521 2025-05-27 xs if test -n "$latest_date"; then
957 0253bef1 2025-05-29 xs find "$R7_RUNDIR" -type f -name "$latest.*"
958 03d8f521 2025-05-27 xs fi
959 46924c01 2025-05-28 xs )
960 03d8f521 2025-05-27 xs
961 46924c01 2025-05-28 xs _output_files() (
962 46924c01 2025-05-28 xs cd "$R7_OUTPUTDIR" 2>/dev/null || return 2
963 03d8f521 2025-05-27 xs find ./* -type f -name 'output'
964 03d8f521 2025-05-27 xs )
965 03d8f521 2025-05-27 xs
966 46924c01 2025-05-28 xs _status_files() (
967 46924c01 2025-05-28 xs cd "$R7_OUTPUTDIR" 2>/dev/null || return 2
968 03d8f521 2025-05-27 xs find ./* -type f -name 'status'
969 03d8f521 2025-05-27 xs )
970 03d8f521 2025-05-27 xs
971 46924c01 2025-05-28 xs _duration_files() (
972 46924c01 2025-05-28 xs cd "$R7_OUTPUTDIR" 2>/dev/null || return 2
973 03d8f521 2025-05-27 xs find ./* -type f -name 'duration'
974 03d8f521 2025-05-27 xs )
975 03d8f521 2025-05-27 xs
976 f6bdfddc 2025-06-03 xs _column() {
977 f6bdfddc 2025-06-03 xs column -t 2>/dev/null ||
978 f6bdfddc 2025-06-03 xs cat -
979 f6bdfddc 2025-06-03 xs }
980 f6bdfddc 2025-06-03 xs
981 46924c01 2025-05-28 xs alias output-status=output_status
982 46924c01 2025-05-28 xs alias outstat=output_status
983 03d8f521 2025-05-27 xs output_status() (
984 46924c01 2025-05-28 xs cd "$R7_OUTPUTDIR" || return 2
985 f6bdfddc 2025-06-03 xs echo HOST GROUP FUNCTION STATUS
986 46924c01 2025-05-28 xs _status_files | {
987 03d8f521 2025-05-27 xs while read -r status; do
988 03d8f521 2025-05-27 xs echo "$status" | while IFS=/ read -r _ host groupname funcname _; do
989 03d8f521 2025-05-27 xs echo "$host" "$groupname" "$funcname" "$(cat "$status")"
990 03d8f521 2025-05-27 xs done
991 03d8f521 2025-05-27 xs done
992 f6bdfddc 2025-06-03 xs } | _column
993 03d8f521 2025-05-27 xs )
994 03d8f521 2025-05-27 xs
995 46924c01 2025-05-28 xs alias output-duration=output_duration
996 46924c01 2025-05-28 xs alias outdur=output_duration
997 03d8f521 2025-05-27 xs output_duration() (
998 730e151b 2025-06-02 xs cd "$R7_OUTPUTDIR" || return 2
999 f6bdfddc 2025-06-03 xs echo HOST GROUP DURATION
1000 46924c01 2025-05-28 xs _duration_files | {
1001 03d8f521 2025-05-27 xs while read -r duration; do
1002 03d8f521 2025-05-27 xs echo "$duration" | while IFS=/ read -r _ host groupname _; do
1003 03d8f521 2025-05-27 xs echo "$host" "$groupname" "$(cat "$duration")"
1004 03d8f521 2025-05-27 xs done
1005 03d8f521 2025-05-27 xs done
1006 f6bdfddc 2025-06-03 xs } | _column
1007 03d8f521 2025-05-27 xs )
1008 03d8f521 2025-05-27 xs
1009 46924c01 2025-05-28 xs alias out=output
1010 87bce7c5 2025-05-30 xs # shellcheck disable=SC2254
1011 03d8f521 2025-05-27 xs output() (
1012 730e151b 2025-06-02 xs cd "$R7_OUTPUTDIR" || return 2
1013 46924c01 2025-05-28 xs _output_files | while read -r output; do
1014 03d8f521 2025-05-27 xs echo "$output" | while IFS=/ read -r _ host groupname funcname _; do
1015 87bce7c5 2025-05-30 xs case $host in ${1:-*})
1016 87bce7c5 2025-05-30 xs case $groupname in ${2:-*})
1017 87bce7c5 2025-05-30 xs case $funcname in ${3:-*})
1018 87bce7c5 2025-05-30 xs echo "- $host" "$groupname" "$funcname"
1019 87bce7c5 2025-05-30 xs echo
1020 87bce7c5 2025-05-30 xs sed 's/^/ /' "$R7_OUTPUTDIR/$output"
1021 87bce7c5 2025-05-30 xs echo
1022 87bce7c5 2025-05-30 xs ;;
1023 87bce7c5 2025-05-30 xs esac
1024 87bce7c5 2025-05-30 xs ;;
1025 87bce7c5 2025-05-30 xs esac
1026 87bce7c5 2025-05-30 xs ;;
1027 87bce7c5 2025-05-30 xs esac
1028 03d8f521 2025-05-27 xs done
1029 03d8f521 2025-05-27 xs done
1030 03d8f521 2025-05-27 xs )
1031 03d8f521 2025-05-27 xs
1032 46924c01 2025-05-28 xs alias trace-id-last=trace_id_last
1033 46924c01 2025-05-28 xs alias lastid=trace_id_last
1034 46924c01 2025-05-28 xs trace_id_last() {
1035 46924c01 2025-05-28 xs output_latest | while read -r output; do
1036 46924c01 2025-05-28 xs output=${output##*/}
1037 46924c01 2025-05-28 xs output=${output%%.*}
1038 46924c01 2025-05-28 xs echo "$output"
1039 46924c01 2025-05-28 xs break
1040 46924c01 2025-05-28 xs done
1041 46924c01 2025-05-28 xs }
1042 46924c01 2025-05-28 xs
1043 46924c01 2025-05-28 xs # _output/tools0/r7test/r7test_diff/output::: 1748408055 tools0 DIFF /tmp/difftest r7test.dir/difftest
1044 46924c01 2025-05-28 xs alias output-diffs=output_diffs
1045 46924c01 2025-05-28 xs alias outdiffs=output_diffs
1046 46924c01 2025-05-28 xs # shellcheck disable=SC2048,SC2086
1047 46924c01 2025-05-28 xs output_diffs() (
1048 46924c01 2025-05-28 xs trace_id=$(trace_id_last)
1049 0253bef1 2025-05-29 xs cd "$R7_OUTPUTDIR" || return 0
1050 730e151b 2025-06-02 xs grep -r "^:: ${trace_id:-} .* DIFF" | uniq | while read -r line; do
1051 46924c01 2025-05-28 xs set -- $line
1052 46924c01 2025-05-28 xs output_file=${1%%:::}
1053 46924c01 2025-05-28 xs OIFS=$IFS
1054 46924c01 2025-05-28 xs IFS=/
1055 46924c01 2025-05-28 xs set -- $output_file
1056 0253bef1 2025-05-29 xs host=$1 groupname=$2 funcname=$3
1057 46924c01 2025-05-28 xs IFS=$OIFS
1058 f83445b1 2025-05-30 xs echo "- (diff) -" "in" "$host" "$groupname" "$funcname" "($trace_id)"
1059 46924c01 2025-05-28 xs echo
1060 46924c01 2025-05-28 xs sed 's/^/ /' "$R7_OUTPUTDIR/$host/$groupname/$funcname/output" | grep -v "^ :: $trace_id $host"
1061 46924c01 2025-05-28 xs echo
1062 730e151b 2025-06-02 xs done || return 0
1063 730e151b 2025-06-02 xs return 0
1064 46924c01 2025-05-28 xs )
1065 46924c01 2025-05-28 xs
1066 46924c01 2025-05-28 xs # :: 1748415578 tools0 PERMISSIONS CHANGE -rw-r-xr-x root wheel -> -rw-r--r-- root wheel on /tmp/difftest
1067 46924c01 2025-05-28 xs alias output-permissions=output_permissions
1068 46924c01 2025-05-28 xs alias outperm=output_permissions
1069 46924c01 2025-05-28 xs # shellcheck disable=SC2048,SC2086
1070 46924c01 2025-05-28 xs output_permissions() (
1071 46924c01 2025-05-28 xs trace_id=$(trace_id_last)
1072 730e151b 2025-06-02 xs cd "$R7_OUTPUTDIR" || return 0
1073 730e151b 2025-06-02 xs grep -r "^:: ${trace_id:-} .* PERMISSIONS" | while read -r line; do
1074 46924c01 2025-05-28 xs set -- $line
1075 46924c01 2025-05-28 xs output_file=${1%%:::}
1076 46924c01 2025-05-28 xs OIFS=$IFS
1077 46924c01 2025-05-28 xs IFS=/
1078 46924c01 2025-05-28 xs set -- $output_file
1079 730e151b 2025-06-02 xs host=$1 groupname=$2 funcname=$3
1080 46924c01 2025-05-28 xs IFS=$OIFS
1081 f83445b1 2025-05-30 xs echo "- (permissions) -" "in" "$host" "$groupname" "$funcname" "($trace_id)"
1082 46924c01 2025-05-28 xs echo
1083 730e151b 2025-06-02 xs grep -e "^:: ${trace_id:-} .* PERMISSIONS CHANGE" "$R7_OUTPUTDIR/$host/$groupname/$funcname/output" |
1084 730e151b 2025-06-02 xs while read -r _ _ _ _ _ mode owner group _ mode2 owner2 group2 _ filename; do
1085 730e151b 2025-06-02 xs echo " - $filename from $mode $owner:$group to $mode2 $owner2:$group2"
1086 730e151b 2025-06-02 xs done
1087 46924c01 2025-05-28 xs echo
1088 46924c01 2025-05-28 xs done
1089 730e151b 2025-06-02 xs return 0
1090 46924c01 2025-05-28 xs )
1091 46924c01 2025-05-28 xs
1092 46924c01 2025-05-28 xs alias output-errors=output_errors
1093 46924c01 2025-05-28 xs alias outerr=output_errors
1094 46924c01 2025-05-28 xs output_errors() (
1095 f83445b1 2025-05-30 xs trace_id=$(trace_id_last)
1096 f6bdfddc 2025-06-03 xs output_status | while read -r host groupname funcname status; do
1097 b7a0ae1e 2025-05-27 xs case $status in
1098 f6bdfddc 2025-06-03 xs STATUS | 0 | 30 | 31) continue ;;
1099 b7a0ae1e 2025-05-27 xs esac
1100 f83445b1 2025-05-30 xs echo "- (error $status) -" "in" "$host" "$groupname" "$funcname" "($trace_id)"
1101 46924c01 2025-05-28 xs if test -f "$R7_OUTPUTDIR/$host/$groupname/$funcname/output"; then
1102 46924c01 2025-05-28 xs echo
1103 46924c01 2025-05-28 xs sed 's/^/ /' "$R7_OUTPUTDIR/$host/$groupname/$funcname/output"
1104 46924c01 2025-05-28 xs echo
1105 46924c01 2025-05-28 xs fi
1106 b7a0ae1e 2025-05-27 xs done
1107 730e151b 2025-06-02 xs return 0
1108 46924c01 2025-05-28 xs )
1109 b7a0ae1e 2025-05-27 xs
1110 46924c01 2025-05-28 xs summary() (
1111 0253bef1 2025-05-29 xs test -d "$R7_OUTPUTDIR" || return 0
1112 0253bef1 2025-05-29 xs summary_out=$(
1113 0253bef1 2025-05-29 xs output_errors
1114 0253bef1 2025-05-29 xs output_diffs
1115 0253bef1 2025-05-29 xs output_permissions
1116 0253bef1 2025-05-29 xs )
1117 0253bef1 2025-05-29 xs test -n "$summary_out" &&
1118 0253bef1 2025-05-29 xs printf "%s\n" "$summary_out"
1119 730e151b 2025-06-02 xs return 0
1120 46924c01 2025-05-28 xs )
1121 46924c01 2025-05-28 xs
1122 03d8f521 2025-05-27 xs # Digraph functions
1123 03d8f521 2025-05-27 xs # =================
1124 03d8f521 2025-05-27 xs
1125 03d8f521 2025-05-27 xs # Used in the digraph generation because inside a heredoc
1126 03d8f521 2025-05-27 xs # context, memebers don't work as expected (OKSH).
1127 46924c01 2025-05-28 xs # shellcheck disable=SC2048,SC2086
1128 46924c01 2025-05-28 xs _members2() (
1129 03d8f521 2025-05-27 xs case $1 in
1130 03d8f521 2025-05-27 xs "'.*'")
1131 03d8f521 2025-05-27 xs nodes | grep -e '.*'
1132 03d8f521 2025-05-27 xs return 0
1133 03d8f521 2025-05-27 xs ;;
1134 03d8f521 2025-05-27 xs esac
1135 03d8f521 2025-05-27 xs set -f -- $(printf -- "-e %s " "$@")
1136 46924c01 2025-05-28 xs nodes | grep $*
1137 03d8f521 2025-05-27 xs )
1138 03d8f521 2025-05-27 xs
1139 46924c01 2025-05-28 xs alias digraph-host=digraph_host
1140 46924c01 2025-05-28 xs # shellcheck disable=SC2086
1141 03d8f521 2025-05-27 xs digraph_host() (
1142 46924c01 2025-05-28 xs _debug "DIGRAPH HOST"
1143 03d8f521 2025-05-27 xs cat <<-eof
1144 03d8f521 2025-05-27 xs digraph host {
1145 03d8f521 2025-05-27 xs layout="dot"
1146 03d8f521 2025-05-27 xs splines="true"
1147 03d8f521 2025-05-27 xs graph [overlap="false", rankdir=LR, mode=KK]
1148 03d8f521 2025-05-27 xs $(
1149 03d8f521 2025-05-27 xs set -f
1150 03d8f521 2025-05-27 xs for node in $(nodes); do echo "\"$node\" [peripheries=2 color=blue]"; done
1151 46924c01 2025-05-28 xs grep 2>/dev/null "^group" "$R7_SITE_CONFIG" | while read -r _ groupname nodes; do
1152 03d8f521 2025-05-27 xs echo "\"$groupname\" [color=orange]"
1153 46924c01 2025-05-28 xs for node in $(_members2 $nodes); do
1154 03d8f521 2025-05-27 xs echo "\"$node\" -> \"$groupname\""
1155 03d8f521 2025-05-27 xs done
1156 46924c01 2025-05-28 xs for funct in $(group_functions "$groupname"); do
1157 730e151b 2025-06-02 xs echo "\"$groupname::$funct\" [color=red]"
1158 730e151b 2025-06-02 xs echo "\"$groupname\" -> \"$groupname::$funct\""
1159 03d8f521 2025-05-27 xs done
1160 03d8f521 2025-05-27 xs done
1161 03d8f521 2025-05-27 xs )
1162 03d8f521 2025-05-27 xs }
1163 03d8f521 2025-05-27 xs eof
1164 03d8f521 2025-05-27 xs )
1165 03d8f521 2025-05-27 xs
1166 f83445b1 2025-05-30 xs alias digraph-ssh-id-hosts=digraph_ssh_id_hosts
1167 f83445b1 2025-05-30 xs digraph_ssh_id_hosts() {
1168 730e151b 2025-06-02 xs cat <<-eof
1169 730e151b 2025-06-02 xs digraph ssh_id_hosts {
1170 730e151b 2025-06-02 xs layout="dot"
1171 730e151b 2025-06-02 xs splines="true"
1172 730e151b 2025-06-02 xs graph [overlap="false"]
1173 730e151b 2025-06-02 xs $(ssh_ids_hosts)
1174 730e151b 2025-06-02 xs }
1175 730e151b 2025-06-02 xs eof
1176 f83445b1 2025-05-30 xs }
1177 f83445b1 2025-05-30 xs
1178 31e019a2 2025-05-31 xs # Html
1179 31e019a2 2025-05-31 xs # ====
1180 730e151b 2025-06-02 xs # TODO: WIP
1181 31e019a2 2025-05-31 xs
1182 6e564797 2025-06-06 xs # shellcheck disable=SC2120
1183 31e019a2 2025-05-31 xs md() {
1184 730e151b 2025-06-02 xs pandoc -t html -f markdown+smart "$@"
1185 31e019a2 2025-05-31 xs }
1186 31e019a2 2025-05-31 xs
1187 8fe13599 2025-06-05 xs _doc() {
1188 8fe13599 2025-06-05 xs output \* \* doc\* | grep ^- | while read -r _ host group function; do
1189 8fe13599 2025-06-05 xs cat "$R7_OUTPUTDIR/$host/$group/$function/output"
1190 8fe13599 2025-06-05 xs echo
1191 8fe13599 2025-06-05 xs done
1192 8fe13599 2025-06-05 xs }
1193 8fe13599 2025-06-05 xs
1194 8fe13599 2025-06-05 xs _summary() {
1195 0551e9c2 2025-06-04 xs summary | while read -r line; do
1196 0551e9c2 2025-06-04 xs set -- $line
1197 0551e9c2 2025-06-04 xs case $1 in
1198 0551e9c2 2025-06-04 xs -)
1199 0551e9c2 2025-06-04 xs printf %s\\n "$line"
1200 0551e9c2 2025-06-04 xs ;;
1201 0551e9c2 2025-06-04 xs *) continue ;;
1202 0551e9c2 2025-06-04 xs esac
1203 0551e9c2 2025-06-04 xs echo
1204 0551e9c2 2025-06-04 xs echo '```'
1205 0551e9c2 2025-06-04 xs cat "$R7_OUTPUTDIR/$6/$7/$8/output"
1206 0551e9c2 2025-06-04 xs echo '```'
1207 0551e9c2 2025-06-04 xs done
1208 0551e9c2 2025-06-04 xs }
1209 0551e9c2 2025-06-04 xs
1210 31e019a2 2025-05-31 xs html() {
1211 0551e9c2 2025-06-04 xs _debug HTML
1212 688c9bfd 2025-06-03 xs cat <<-eof
1213 688c9bfd 2025-06-03 xs <!DOCTYPE html>
1214 688c9bfd 2025-06-03 xs <html lang="en">
1215 4459883d 2025-06-05 xs <head>
1216 4459883d 2025-06-05 xs <meta charset="UTF-8">
1217 4459883d 2025-06-05 xs <meta name="viewport" content="width=device-width,initial-scale=1">
1218 4459883d 2025-06-05 xs <title>${PWD##*/}</title>
1219 4459883d 2025-06-05 xs <style>
1220 4459883d 2025-06-05 xs body{margin:1rem;background:#f5f7fa;color:#333;font:14px/1.5 Consolas,monospace}
1221 4459883d 2025-06-05 xs .container{max-width:800px;margin:0 auto;padding:1.5rem;background:#fff;box-shadow:0 1px 4px rgba(0,0,0,0.05);border-radius:3px}
1222 4459883d 2025-06-05 xs header{border-bottom:1px solid #ddd;margin-bottom:1rem;padding-bottom:.5rem}
1223 4459883d 2025-06-05 xs header h1{margin:0;font-size:1.4rem;font-weight:400}
1224 4459883d 2025-06-05 xs header time{font-size:.85rem;color:#666}
1225 4459883d 2025-06-05 xs .summary{border-bottom:1px dashed #eee;padding:.5rem 0}
1226 4459883d 2025-06-05 xs .summary:last-child{border:none;padding:0}
1227 4459883d 2025-06-05 xs .timestamp{display:block;font-size:.8rem;color:#555;margin-bottom:.25rem}
1228 4459883d 2025-06-05 xs </style>
1229 4459883d 2025-06-05 xs </head>
1230 4459883d 2025-06-05 xs <body>
1231 4459883d 2025-06-05 xs <div class="container">
1232 4459883d 2025-06-05 xs <header>
1233 4459883d 2025-06-05 xs <h1>Summary</h1>
1234 4459883d 2025-06-05 xs </header>
1235 4459883d 2025-06-05 xs <section class="summary">
1236 4459883d 2025-06-05 xs $(_summary | md)
1237 4459883d 2025-06-05 xs </section>
1238 4459883d 2025-06-05 xs <section class="summary">
1239 4459883d 2025-06-05 xs $(_doc | md)
1240 4459883d 2025-06-05 xs </section>
1241 4459883d 2025-06-05 xs </div>
1242 4459883d 2025-06-05 xs </body>
1243 688c9bfd 2025-06-03 xs </html>
1244 688c9bfd 2025-06-03 xs eof
1245 8a9cbf90 2025-06-04 xs return 0
1246 31e019a2 2025-05-31 xs }
1247 31e019a2 2025-05-31 xs
1248 730e151b 2025-06-02 xs # Importers
1249 730e151b 2025-06-02 xs # =========
1250 730e151b 2025-06-02 xs
1251 730e151b 2025-06-02 xs import() {
1252 d8747c12 2025-06-03 xs cd "$R7_WORKDIR" || _fail "Unable to cd to '$R7_WORKDIR'"
1253 730e151b 2025-06-02 xs target=$1
1254 a4759196 2025-06-13 xs if test -n "$target"; then
1255 a4759196 2025-06-13 xs echo >&2 "-> Importing target host: $target"
1256 a4759196 2025-06-13 xs case $(ssh "$target" uname) in
1257 a4759196 2025-06-13 xs Linux) _Linux_import ;;
1258 a4759196 2025-06-13 xs SunOS) _SunOS_import ;;
1259 a4759196 2025-06-13 xs OpenBSD) _OpenBSD_import ;;
1260 a4759196 2025-06-13 xs FreeBSD) _FreeBSD_import ;;
1261 a4759196 2025-06-13 xs NetBSD) _NetBSD_import ;;
1262 a4759196 2025-06-13 xs DragonFly) _DragonFly_import ;;
1263 8e44e3d4 2025-06-25 xs Haiku) _Haiku_import ;;
1264 8e44e3d4 2025-06-25 xs QNX) _QNX_import ;;
1265 8e44e3d4 2025-06-25 xs Minix) _Minix_import ;;
1266 a4759196 2025-06-13 xs *)
1267 a4759196 2025-06-13 xs _error "Platform unsupported or host unavailable."
1268 a4759196 2025-06-13 xs return 3
1269 a4759196 2025-06-13 xs ;;
1270 a4759196 2025-06-13 xs esac
1271 a4759196 2025-06-13 xs echo >&2 "-> done: $target"
1272 a4759196 2025-06-13 xs else
1273 a4759196 2025-06-13 xs echo >&2 "usage: $0 target-host"
1274 a4759196 2025-06-13 xs fi
1275 a4759196 2025-06-13 xs }
1276 a4759196 2025-06-13 xs
1277 a4759196 2025-06-13 xs _import_copy() (
1278 a4759196 2025-06-13 xs src=$1
1279 a4759196 2025-06-13 xs dst=$2
1280 a4759196 2025-06-13 xs _debug "COPY $src $dst"
1281 a4759196 2025-06-13 xs ssh "$target" command -v rsync >/dev/null && {
1282 a4759196 2025-06-13 xs _debug "IMPORT $1 $2 USE RSYNC"
1283 622e6949 2025-06-13 xs rsync -e "/usr/bin/ssh -oConnectTimeout=$SSH_CONNECT_TIMEOUT -F $SSH_CONFIG_FILE" \
1284 622e6949 2025-06-13 xs -a "$src" "$dst" && return 0
1285 a4759196 2025-06-13 xs }
1286 a4759196 2025-06-13 xs _openrsync=$(ssh "$target" command -v openrsync) && {
1287 a4759196 2025-06-13 xs _debug "IMPORT $1 $2 USE OPENRSYNC"
1288 a4759196 2025-06-13 xs openrsync -e "/usr/bin/ssh -oConnectTimeout=$SSH_CONNECT_TIMEOUT -F $SSH_CONFIG_FILE" \
1289 a4759196 2025-06-13 xs --rsync-path="$_openrsync" \
1290 a4759196 2025-06-13 xs -a "$src" "$dst" && return 0
1291 a4759196 2025-06-13 xs }
1292 a4759196 2025-06-13 xs _debug "IMPORT $1 $2 USE SCP"
1293 8e44e3d4 2025-06-25 xs scp "-oConnectTimeout=$SSH_CONNECT_TIMEOUT" -qF "$SSH_CONFIG_FILE" -r "$src" "$dst" && return 0
1294 a4759196 2025-06-13 xs _fail "IMPORT $1 $2 FAILED"
1295 a4759196 2025-06-13 xs )
1296 a4759196 2025-06-13 xs
1297 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys_old() (
1298 8e44e3d4 2025-06-25 xs set +e
1299 a4759196 2025-06-13 xs other_users=$(
1300 a4759196 2025-06-13 xs ssh "$target" getent passwd | awk -F: '$3 >= 1000 { print $1 }' |
1301 a4759196 2025-06-13 xs grep -v nobody
1302 a4759196 2025-06-13 xs )
1303 a4759196 2025-06-13 xs
1304 a4759196 2025-06-13 xs for user in root $other_users; do
1305 a4759196 2025-06-13 xs # shellcheck disable=SC2029
1306 a4759196 2025-06-13 xs home=$(ssh "$target" getent passwd "$user" | awk -F: '{ print $6 }')
1307 a4759196 2025-06-13 xs authorized_keys="$home/.ssh/authorized_keys"
1308 a4759196 2025-06-13 xs ssh "$target" test -f "$authorized_keys" || continue
1309 a4759196 2025-06-13 xs mkdir -p "nodes/$target/ssh/"
1310 a4759196 2025-06-13 xs echo >&2 "--> Importing $authorized_keys"
1311 8e44e3d4 2025-06-25 xs _import_copy "$target:$authorized_keys" "nodes/$target/ssh/authorized_keys_$user"
1312 a4759196 2025-06-13 xs done
1313 8e44e3d4 2025-06-25 xs )
1314 a4759196 2025-06-13 xs
1315 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys() (
1316 8e44e3d4 2025-06-25 xs set +e
1317 8e44e3d4 2025-06-25 xs other_users=$(
1318 8e44e3d4 2025-06-25 xs ssh "$target" cat /etc/passwd | awk -F: '$3 >= 1000 { print $1 }' | grep -v nobody
1319 8e44e3d4 2025-06-25 xs )
1320 8e44e3d4 2025-06-25 xs for user in root $other_users; do
1321 8e44e3d4 2025-06-25 xs home=$(
1322 8e44e3d4 2025-06-25 xs ssh "$target" cat /etc/passwd | awk -F: -v user="$user" '$1 == user { print $6 }'
1323 8e44e3d4 2025-06-25 xs )
1324 8e44e3d4 2025-06-25 xs authorized_keys="$home/.ssh/authorized_keys"
1325 8e44e3d4 2025-06-25 xs if ! ssh -n "$target" test -f "$authorized_keys"; then
1326 8e44e3d4 2025-06-25 xs continue
1327 8e44e3d4 2025-06-25 xs fi
1328 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/ssh/"
1329 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing $authorized_keys for user='$user'"
1330 8e44e3d4 2025-06-25 xs _import_copy "$target:$authorized_keys" "nodes/$target/ssh/authorized_keys_$user"
1331 8e44e3d4 2025-06-25 xs done
1332 8e44e3d4 2025-06-25 xs )
1333 8e44e3d4 2025-06-25 xs
1334 a4759196 2025-06-13 xs _import_etc_if_exists() {
1335 a4759196 2025-06-13 xs mkdir -p nodes/"$target"
1336 a4759196 2025-06-13 xs echo >&2 "--> Importing /etc"
1337 a4759196 2025-06-13 xs for file in $etc_files_to_import; do
1338 a4759196 2025-06-13 xs ssh "$target" test -f "'/etc/$file'" &&
1339 a4759196 2025-06-13 xs _import_copy "$target:/etc/$file" "nodes/$target"
1340 a4759196 2025-06-13 xs done
1341 a4759196 2025-06-13 xs }
1342 a4759196 2025-06-13 xs
1343 a4759196 2025-06-13 xs _import_etc_ssh_if_exists() {
1344 8e44e3d4 2025-06-25 xs etc_ssh_files_to_import='
1345 8e44e3d4 2025-06-25 xs ssh/sshd_config
1346 8e44e3d4 2025-06-25 xs ssh/ssh_config
1347 8e44e3d4 2025-06-25 xs '
1348 8e44e3d4 2025-06-25 xs mkdir -p nodes/"$target/ssh"
1349 a4759196 2025-06-13 xs echo >&2 "--> Importing /etc/ssh"
1350 a4759196 2025-06-13 xs for file in $etc_ssh_files_to_import; do
1351 a4759196 2025-06-13 xs ssh "$target" test -f "'/etc/$file'" &&
1352 a4759196 2025-06-13 xs _import_copy "$target:/etc/$file" "nodes/$target/ssh"
1353 a4759196 2025-06-13 xs done
1354 a4759196 2025-06-13 xs }
1355 a4759196 2025-06-13 xs
1356 a4759196 2025-06-13 xs _import_modprobe() {
1357 8e44e3d4 2025-06-25 xs if ssh "$target" test -d /etc/modprobe.d; then
1358 8e44e3d4 2025-06-25 xs _content=$(ssh "$target" ls -A /etc/modprobe.d/)
1359 8e44e3d4 2025-06-25 xs test -z "$_content" && return 0
1360 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/modprobe.d"
1361 8e44e3d4 2025-06-25 xs mkdir -p nodes/"$target/modprobe.d"
1362 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/modprobe.d/*" "nodes/$target/modprobe.d"
1363 8e44e3d4 2025-06-25 xs fi
1364 a4759196 2025-06-13 xs }
1365 a4759196 2025-06-13 xs
1366 8e44e3d4 2025-06-25 xs _QNX_import() {
1367 8e44e3d4 2025-06-25 xs etc_files_to_import='
1368 8e44e3d4 2025-06-25 xs build.date
1369 8e44e3d4 2025-06-25 xs '
1370 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1371 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/settings"
1372 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/settings"
1373 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/settings" "nodes/$target/settings"
1374 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /system/etc/ssh"
1375 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/ssh"
1376 8e44e3d4 2025-06-25 xs _import_copy "$target:/system/etc/ssh/sshd_config" "nodes/$target/ssh"
1377 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1378 8e44e3d4 2025-06-25 xs }
1379 8e44e3d4 2025-06-25 xs
1380 8e44e3d4 2025-06-25 xs _Minix_import() {
1381 8e44e3d4 2025-06-25 xs etc_files_to_import='
1382 8e44e3d4 2025-06-25 xs fstab
1383 8e44e3d4 2025-06-25 xs inet.conf
1384 8e44e3d4 2025-06-25 xs profile
1385 8e44e3d4 2025-06-25 xs resolv.conf
1386 8e44e3d4 2025-06-25 xs shells
1387 8e44e3d4 2025-06-25 xs rc.conf
1388 8e44e3d4 2025-06-25 xs '
1389 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1390 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /usr/pkg/etc/ssh"
1391 8e44e3d4 2025-06-25 xs mkdir -p nodes/"$target/ssh"
1392 8e44e3d4 2025-06-25 xs _import_copy "$target:/usr/pkg/etc/ssh/sshd_config" "nodes/$target/ssh"
1393 8e44e3d4 2025-06-25 xs _import_copy "$target:/usr/pkg/etc/ssh/ssh_config" "nodes/$target/ssh"
1394 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /usr/pkg/etc/pkgin"
1395 8e44e3d4 2025-06-25 xs mkdir -p nodes/"$target/pkgin"
1396 8e44e3d4 2025-06-25 xs _import_copy "$target:/usr/pkg/etc/pkgin/repositories.conf" "nodes/$target/pkgin"
1397 8e44e3d4 2025-06-25 xs }
1398 8e44e3d4 2025-06-25 xs
1399 8e44e3d4 2025-06-25 xs _Haiku_import() {
1400 8e44e3d4 2025-06-25 xs etc_files_to_import='
1401 8e44e3d4 2025-06-25 xs inputrc
1402 8e44e3d4 2025-06-25 xs profile
1403 8e44e3d4 2025-06-25 xs '
1404 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1405 8e44e3d4 2025-06-25 xs _import_copy "$target:/boot/system/settings/network/hosts" "nodes/$target/"
1406 8e44e3d4 2025-06-25 xs _import_copy "$target:/boot/system/settings/network/resolv.conf" "nodes/$target/"
1407 8e44e3d4 2025-06-25 xs _import_copy "$target:/boot/system/settings/package-repositories" "nodes/$target/"
1408 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /boot/system/settings/ssh"
1409 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/ssh"
1410 8e44e3d4 2025-06-25 xs _import_copy "$target:/boot/system/settings/ssh/sshd_config" "nodes/$target/ssh"
1411 8e44e3d4 2025-06-25 xs _import_copy "$target:/boot/system/settings/ssh/ssh_config" "nodes/$target/ssh"
1412 8e44e3d4 2025-06-25 xs _import_copy "$target:/boot/home/config/settings/ssh/authorized_keys" \
1413 8e44e3d4 2025-06-25 xs "nodes/$target/ssh/authorized_keys_user"
1414 8e44e3d4 2025-06-25 xs }
1415 8e44e3d4 2025-06-25 xs
1416 a4759196 2025-06-13 xs _Linux_import() {
1417 a4759196 2025-06-13 xs if _Linux_is_debian_based; then
1418 a4759196 2025-06-13 xs _Linux_import_debian
1419 a4759196 2025-06-13 xs elif _Linux_is_rhel_based; then
1420 a4759196 2025-06-13 xs _Linux_import_rhel
1421 8e44e3d4 2025-06-25 xs elif _Linux_is_suse_based; then
1422 8e44e3d4 2025-06-25 xs _Linux_import_suse
1423 a4759196 2025-06-13 xs elif _Linux_is_gentoo_based; then
1424 a4759196 2025-06-13 xs _Linux_import_gentoo
1425 8e44e3d4 2025-06-25 xs elif _Linux_is_arch_based; then
1426 8e44e3d4 2025-06-25 xs _Linux_import_arch
1427 8e44e3d4 2025-06-25 xs elif _Linux_is_artix; then
1428 8e44e3d4 2025-06-25 xs _Linux_import_artix
1429 a4759196 2025-06-13 xs elif ssh "$target" "grep -q 'ID=alpine' /etc/os-release"; then
1430 a4759196 2025-06-13 xs _Linux_import_alpine
1431 8e44e3d4 2025-06-25 xs elif ssh "$target" "grep -q 'ID=crux' /etc/os-release"; then
1432 8e44e3d4 2025-06-25 xs _Linux_import_crux
1433 8e44e3d4 2025-06-25 xs elif ssh "$target" "grep -q 'ID=\"void\"' /etc/os-release"; then
1434 8e44e3d4 2025-06-25 xs _Linux_import_void
1435 8e44e3d4 2025-06-25 xs elif ssh "$target" "grep -q 'ID=guix' /etc/os-release"; then
1436 8e44e3d4 2025-06-25 xs _Linux_import_guix
1437 a4759196 2025-06-13 xs else
1438 a4759196 2025-06-13 xs echo >&2 "Unsupported Linux distribution."
1439 a4759196 2025-06-13 xs fi
1440 a4759196 2025-06-13 xs }
1441 a4759196 2025-06-13 xs
1442 a4759196 2025-06-13 xs _Linux_is_debian_based() (
1443 8e44e3d4 2025-06-25 xs ssh "$target" "grep -q 'ID=debian' /etc/os-release || \
1444 8e44e3d4 2025-06-25 xs grep -q 'ID_LIKE=.*debian' /etc/os-release || \
1445 8e44e3d4 2025-06-25 xs grep -qiE 'Debian|Ubuntu|Linux Mint' /etc/issue || \
1446 8e44e3d4 2025-06-25 xs test -f /etc/debian_version || test -d /etc/apt || command -v apt-get >/dev/null 2>&1" 2>/dev/null
1447 a4759196 2025-06-13 xs )
1448 a4759196 2025-06-13 xs
1449 a4759196 2025-06-13 xs _Linux_is_rhel_based() (
1450 8e44e3d4 2025-06-25 xs ssh "$target" "grep -qiE 'ID=\"?(rhel|fedora|centos|ol|scientific|rocky|eurolinux)\"?' /etc/os-release || \
1451 8e44e3d4 2025-06-25 xs grep -qiE 'ID_LIKE=\"?.*(rhel|fedora).*\"?' /etc/os-release || \
1452 8e44e3d4 2025-06-25 xs grep -qiE 'Red Hat|CentOS|Fedora|Scientific Linux|Oracle Linux' /etc/issue || \
1453 8e44e3d4 2025-06-25 xs test -f /etc/redhat-release || test -f /etc/system-release || test -f /etc/centos-release || \
1454 8e44e3d4 2025-06-25 xs test -f /etc/fedora-release || test -f /etc/oracle-release || \
1455 8e44e3d4 2025-06-25 xs (test -f /etc/os-release && grep -qi 'rhel' /etc/os-release) || test -d /etc/yum.repos.d" 2>/dev/null
1456 a4759196 2025-06-13 xs )
1457 a4759196 2025-06-13 xs
1458 a4759196 2025-06-13 xs _Linux_is_gentoo_based() (
1459 a4759196 2025-06-13 xs ssh "$target" "test -f /etc/gentoo-release || \
1460 8e44e3d4 2025-06-25 xs grep -q 'ID=gentoo' /etc/os-release || \
1461 8e44e3d4 2025-06-25 xs grep -q 'ID=funtoo' /etc/os-release || \
1462 8e44e3d4 2025-06-25 xs grep -qi 'Gentoo' /etc/issue || \
1463 8e44e3d4 2025-06-25 xs command -v emerge >/dev/null 2>&1" 2>/dev/null
1464 a4759196 2025-06-13 xs )
1465 a4759196 2025-06-13 xs
1466 8e44e3d4 2025-06-25 xs _Linux_is_suse_based() (
1467 8e44e3d4 2025-06-25 xs ssh "$target" "test -f /etc/os-release && grep -Eqi \
1468 8e44e3d4 2025-06-25 xs 'suse|opensuse' /etc/os-release || \
1469 8e44e3d4 2025-06-25 xs command -v zypper >/dev/null || \
1470 8e44e3d4 2025-06-25 xs command -v yast2 >/dev/null" 2>/dev/null
1471 8e44e3d4 2025-06-25 xs )
1472 8e44e3d4 2025-06-25 xs
1473 8e44e3d4 2025-06-25 xs _Linux_is_arch_based() (
1474 8e44e3d4 2025-06-25 xs ssh "$target" "test -f /etc/os-release && grep -Eqi \
1475 8e44e3d4 2025-06-25 xs 'arch|manjaro|endeavouros|arcolinux|parabola' /etc/os-release || \
1476 8e44e3d4 2025-06-25 xs command -v pacman >/dev/null || \
1477 8e44e3d4 2025-06-25 xs command -v makepkg >/dev/null" 2>/dev/null
1478 8e44e3d4 2025-06-25 xs )
1479 8e44e3d4 2025-06-25 xs
1480 8e44e3d4 2025-06-25 xs _Linux_is_artix() (
1481 8e44e3d4 2025-06-25 xs ssh "$target" "test -f /etc/os-release && grep -Eqi \
1482 8e44e3d4 2025-06-25 xs 'artix|hyperbola' /etc/os-release || \
1483 8e44e3d4 2025-06-25 xs command -v pacman >/dev/null || \
1484 8e44e3d4 2025-06-25 xs command -v makepkg >/dev/null" 2>/dev/null
1485 8e44e3d4 2025-06-25 xs )
1486 8e44e3d4 2025-06-25 xs
1487 a4759196 2025-06-13 xs _Linux_import_gentoo() {
1488 730e151b 2025-06-02 xs etc_files_to_import='
1489 a4759196 2025-06-13 xs crontab
1490 a4759196 2025-06-13 xs doas.conf
1491 a4759196 2025-06-13 xs environment
1492 a4759196 2025-06-13 xs fstab
1493 a4759196 2025-06-13 xs hostname
1494 a4759196 2025-06-13 xs hosts
1495 a4759196 2025-06-13 xs hosts.denv
1496 a4759196 2025-06-13 xs issue
1497 a4759196 2025-06-13 xs locale.gen
1498 a4759196 2025-06-13 xs machine-id
1499 a4759196 2025-06-13 xs motd
1500 a4759196 2025-06-13 xs nsswitch.conf
1501 a4759196 2025-06-13 xs pam.conf
1502 a4759196 2025-06-13 xs profile
1503 a4759196 2025-06-13 xs shells
1504 a4759196 2025-06-13 xs sudo.conf
1505 a4759196 2025-06-13 xs sudoers
1506 a4759196 2025-06-13 xs sysctl.conf
1507 a4759196 2025-06-13 xs '
1508 a4759196 2025-06-13 xs _import_etc_if_exists
1509 a4759196 2025-06-13 xs _import_etc_ssh_if_exists
1510 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/portage"
1511 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/portage"
1512 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/portage/" "nodes/$target/portage/"
1513 a4759196 2025-06-13 xs _import_ssh_authorized_keys
1514 a4759196 2025-06-13 xs _import_modprobe
1515 a4759196 2025-06-13 xs }
1516 a4759196 2025-06-13 xs
1517 a4759196 2025-06-13 xs _Linux_import_alpine() {
1518 a4759196 2025-06-13 xs etc_files_to_import='
1519 a4759196 2025-06-13 xs crontab
1520 a4759196 2025-06-13 xs doas.conf
1521 a4759196 2025-06-13 xs environment
1522 a4759196 2025-06-13 xs fstab
1523 a4759196 2025-06-13 xs hostname
1524 a4759196 2025-06-13 xs hosts
1525 a4759196 2025-06-13 xs hosts.denv
1526 a4759196 2025-06-13 xs issue
1527 a4759196 2025-06-13 xs motd
1528 a4759196 2025-06-13 xs nsswitch.conf
1529 a4759196 2025-06-13 xs pam.conf
1530 a4759196 2025-06-13 xs profile
1531 a4759196 2025-06-13 xs rc.conf
1532 a4759196 2025-06-13 xs resolv.conf
1533 a4759196 2025-06-13 xs shells
1534 a4759196 2025-06-13 xs sysctl.conf
1535 a4759196 2025-06-13 xs '
1536 a4759196 2025-06-13 xs _import_etc_if_exists
1537 a4759196 2025-06-13 xs _import_etc_ssh_if_exists
1538 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/apk"
1539 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/apk"
1540 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/apk/repositories" "nodes/$target/apk/"
1541 a4759196 2025-06-13 xs _import_ssh_authorized_keys
1542 a4759196 2025-06-13 xs _import_modprobe
1543 a4759196 2025-06-13 xs }
1544 a4759196 2025-06-13 xs
1545 a4759196 2025-06-13 xs _Linux_import_rhel() {
1546 a4759196 2025-06-13 xs etc_files_to_import='
1547 a4759196 2025-06-13 xs crontab
1548 a4759196 2025-06-13 xs environment
1549 a4759196 2025-06-13 xs fstab
1550 a4759196 2025-06-13 xs hostname
1551 a4759196 2025-06-13 xs hosts
1552 a4759196 2025-06-13 xs hosts.denv
1553 a4759196 2025-06-13 xs issue
1554 a4759196 2025-06-13 xs locale.gen
1555 a4759196 2025-06-13 xs machine-id
1556 a4759196 2025-06-13 xs motd
1557 a4759196 2025-06-13 xs nsswitch.conf
1558 a4759196 2025-06-13 xs pam.conf
1559 a4759196 2025-06-13 xs profile
1560 a4759196 2025-06-13 xs resolv.conf
1561 a4759196 2025-06-13 xs shells
1562 a4759196 2025-06-13 xs sudo.conf
1563 a4759196 2025-06-13 xs sudoers
1564 a4759196 2025-06-13 xs '
1565 a4759196 2025-06-13 xs _import_etc_if_exists
1566 a4759196 2025-06-13 xs _import_etc_ssh_if_exists
1567 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/yum.repos.d"
1568 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/yum.repos.d"
1569 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/yum.repos.d/" "nodes/$target/yum.repos.d/"
1570 a4759196 2025-06-13 xs _import_ssh_authorized_keys
1571 a4759196 2025-06-13 xs _import_modprobe
1572 a4759196 2025-06-13 xs }
1573 a4759196 2025-06-13 xs
1574 a4759196 2025-06-13 xs _Linux_import_debian() {
1575 a4759196 2025-06-13 xs etc_files_to_import='
1576 a4759196 2025-06-13 xs crontab
1577 a4759196 2025-06-13 xs environment
1578 a4759196 2025-06-13 xs fstab
1579 a4759196 2025-06-13 xs hostname
1580 a4759196 2025-06-13 xs hosts
1581 a4759196 2025-06-13 xs hosts.denv
1582 a4759196 2025-06-13 xs issue
1583 a4759196 2025-06-13 xs locale.gen
1584 a4759196 2025-06-13 xs machine-id
1585 a4759196 2025-06-13 xs nsswitch.conf
1586 a4759196 2025-06-13 xs pam.conf
1587 a4759196 2025-06-13 xs profile
1588 a4759196 2025-06-13 xs resolv.conf
1589 a4759196 2025-06-13 xs shells
1590 a4759196 2025-06-13 xs sudo.conf
1591 a4759196 2025-06-13 xs sudoers
1592 a4759196 2025-06-13 xs '
1593 a4759196 2025-06-13 xs _import_etc_if_exists
1594 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/apt"
1595 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/apt"
1596 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/apt/sources.list" "nodes/$target/apt"
1597 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/apt/sources.list.d" "nodes/$target/apt"
1598 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/network"
1599 8e44e3d4 2025-06-25 xs mkdir -p "nodes/$target/network/"
1600 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/network/interfaces" "nodes/$target/network/"
1601 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/network/interfaces.d" "nodes/$target/network/"
1602 a4759196 2025-06-13 xs _import_etc_ssh_if_exists
1603 a4759196 2025-06-13 xs _import_ssh_authorized_keys
1604 a4759196 2025-06-13 xs _import_modprobe
1605 8e44e3d4 2025-06-25 xs
1606 a4759196 2025-06-13 xs }
1607 a4759196 2025-06-13 xs
1608 8e44e3d4 2025-06-25 xs _Linux_import_suse() {
1609 8e44e3d4 2025-06-25 xs etc_files_to_import='
1610 8e44e3d4 2025-06-25 xs fstab
1611 8e44e3d4 2025-06-25 xs hosts
1612 8e44e3d4 2025-06-25 xs profile
1613 8e44e3d4 2025-06-25 xs sudo.conf
1614 8e44e3d4 2025-06-25 xs sudoers
1615 8e44e3d4 2025-06-25 xs sysctl.conf
1616 8e44e3d4 2025-06-25 xs environment
1617 8e44e3d4 2025-06-25 xs exports
1618 8e44e3d4 2025-06-25 xs chrony.conf
1619 8e44e3d4 2025-06-25 xs '
1620 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1621 8e44e3d4 2025-06-25 xs _import_etc_ssh_if_exists
1622 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1623 8e44e3d4 2025-06-25 xs _import_modprobe
1624 8e44e3d4 2025-06-25 xs }
1625 8e44e3d4 2025-06-25 xs
1626 8e44e3d4 2025-06-25 xs _Linux_import_arch() {
1627 8e44e3d4 2025-06-25 xs etc_files_to_import='
1628 8e44e3d4 2025-06-25 xs environment
1629 8e44e3d4 2025-06-25 xs hostname
1630 8e44e3d4 2025-06-25 xs profile
1631 8e44e3d4 2025-06-25 xs arch-release
1632 8e44e3d4 2025-06-25 xs issue
1633 8e44e3d4 2025-06-25 xs hosts
1634 8e44e3d4 2025-06-25 xs pacman.conf
1635 8e44e3d4 2025-06-25 xs sudo.conf
1636 8e44e3d4 2025-06-25 xs sudoers
1637 8e44e3d4 2025-06-25 xs fstab
1638 8e44e3d4 2025-06-25 xs '
1639 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1640 8e44e3d4 2025-06-25 xs _import_etc_ssh_if_exists
1641 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1642 8e44e3d4 2025-06-25 xs _import_modprobe
1643 8e44e3d4 2025-06-25 xs }
1644 8e44e3d4 2025-06-25 xs
1645 8e44e3d4 2025-06-25 xs _Linux_import_artix() {
1646 8e44e3d4 2025-06-25 xs _Linux_import_arch
1647 8e44e3d4 2025-06-25 xs }
1648 8e44e3d4 2025-06-25 xs
1649 8e44e3d4 2025-06-25 xs _Linux_import_guix() {
1650 8e44e3d4 2025-06-25 xs etc_files_to_import='
1651 8e44e3d4 2025-06-25 xs config.scm
1652 8e44e3d4 2025-06-25 xs environment
1653 8e44e3d4 2025-06-25 xs fstab
1654 8e44e3d4 2025-06-25 xs hostname
1655 8e44e3d4 2025-06-25 xs hosts
1656 8e44e3d4 2025-06-25 xs issue
1657 8e44e3d4 2025-06-25 xs nsswitch.conf
1658 8e44e3d4 2025-06-25 xs profile
1659 8e44e3d4 2025-06-25 xs resolv.conf
1660 8e44e3d4 2025-06-25 xs shells
1661 8e44e3d4 2025-06-25 xs sudoers
1662 8e44e3d4 2025-06-25 xs '
1663 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1664 8e44e3d4 2025-06-25 xs _import_etc_ssh_if_exists
1665 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1666 8e44e3d4 2025-06-25 xs }
1667 8e44e3d4 2025-06-25 xs
1668 8e44e3d4 2025-06-25 xs _Linux_import_void() {
1669 8e44e3d4 2025-06-25 xs etc_files_to_import='\
1670 8e44e3d4 2025-06-25 xs fstab
1671 8e44e3d4 2025-06-25 xs dhcpcd.conf
1672 8e44e3d4 2025-06-25 xs environment
1673 8e44e3d4 2025-06-25 xs hosts
1674 8e44e3d4 2025-06-25 xs profile
1675 8e44e3d4 2025-06-25 xs rc.conf
1676 8e44e3d4 2025-06-25 xs nsswitch.conf
1677 8e44e3d4 2025-06-25 xs shells
1678 8e44e3d4 2025-06-25 xs sudoers
1679 8e44e3d4 2025-06-25 xs sudo.conf
1680 8e44e3d4 2025-06-25 xs sysctl.conf
1681 8e44e3d4 2025-06-25 xs resolv.conf
1682 8e44e3d4 2025-06-25 xs '
1683 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1684 8e44e3d4 2025-06-25 xs _import_etc_ssh_if_exists
1685 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1686 8e44e3d4 2025-06-25 xs _import_modprobe
1687 8e44e3d4 2025-06-25 xs }
1688 8e44e3d4 2025-06-25 xs
1689 8e44e3d4 2025-06-25 xs _Linux_import_crux() {
1690 8e44e3d4 2025-06-25 xs etc_files_to_import='
1691 8e44e3d4 2025-06-25 xs crontab
1692 8e44e3d4 2025-06-25 xs hosts
1693 8e44e3d4 2025-06-25 xs resolv.conf
1694 8e44e3d4 2025-06-25 xs environment
1695 8e44e3d4 2025-06-25 xs fstab
1696 8e44e3d4 2025-06-25 xs locale.gen
1697 8e44e3d4 2025-06-25 xs hosts
1698 8e44e3d4 2025-06-25 xs profile
1699 8e44e3d4 2025-06-25 xs rc.conf
1700 8e44e3d4 2025-06-25 xs rc.local
1701 8e44e3d4 2025-06-25 xs syslog.conf
1702 8e44e3d4 2025-06-25 xs sysctl.conf
1703 8e44e3d4 2025-06-25 xs '
1704 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1705 8e44e3d4 2025-06-25 xs _import_etc_ssh_if_exists
1706 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1707 8e44e3d4 2025-06-25 xs _import_modprobe
1708 8e44e3d4 2025-06-25 xs }
1709 8e44e3d4 2025-06-25 xs
1710 a4759196 2025-06-13 xs _SunOS_import() {
1711 a4759196 2025-06-13 xs etc_files_to_import='
1712 a4759196 2025-06-13 xs crontab
1713 a4759196 2025-06-13 xs environment
1714 a4759196 2025-06-13 xs fstab
1715 a4759196 2025-06-13 xs hostname
1716 a4759196 2025-06-13 xs hosts
1717 a4759196 2025-06-13 xs hosts.denv
1718 a4759196 2025-06-13 xs issue
1719 a4759196 2025-06-13 xs locale.gen
1720 a4759196 2025-06-13 xs motd
1721 a4759196 2025-06-13 xs nodename
1722 a4759196 2025-06-13 xs nsswitch.conf
1723 a4759196 2025-06-13 xs pam.conf
1724 a4759196 2025-06-13 xs profile
1725 a4759196 2025-06-13 xs profile
1726 a4759196 2025-06-13 xs resolv.conf
1727 a4759196 2025-06-13 xs rsyslog.conf
1728 a4759196 2025-06-13 xs shells
1729 a4759196 2025-06-13 xs sudo.conf
1730 a4759196 2025-06-13 xs sudoers
1731 a4759196 2025-06-13 xs '
1732 a4759196 2025-06-13 xs _import_etc_if_exists
1733 a4759196 2025-06-13 xs _import_etc_ssh_if_exists
1734 a4759196 2025-06-13 xs _import_ssh_authorized_keys
1735 a4759196 2025-06-13 xs }
1736 a4759196 2025-06-13 xs
1737 8e44e3d4 2025-06-25 xs _FreeBSD_import() {
1738 8e44e3d4 2025-06-25 xs etc_files_to_import='
1739 8e44e3d4 2025-06-25 xs crontab
1740 8e44e3d4 2025-06-25 xs fbtab
1741 8e44e3d4 2025-06-25 xs fstab
1742 8e44e3d4 2025-06-25 xs hostname
1743 8e44e3d4 2025-06-25 xs hosts
1744 8e44e3d4 2025-06-25 xs login.conf
1745 8e44e3d4 2025-06-25 xs nsswitch.conf
1746 8e44e3d4 2025-06-25 xs ntp.conf
1747 8e44e3d4 2025-06-25 xs profile
1748 8e44e3d4 2025-06-25 xs resolv.conf
1749 8e44e3d4 2025-06-25 xs shells
1750 8e44e3d4 2025-06-25 xs sysctl.conf
1751 8e44e3d4 2025-06-25 xs syslog.conf
1752 8e44e3d4 2025-06-25 xs '
1753 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1754 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/pkg"
1755 8e44e3d4 2025-06-25 xs _import_copy "$target:/etc/pkg" "nodes/$target/"
1756 8e44e3d4 2025-06-25 xs _import_etc_ssh_if_exists
1757 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1758 8e44e3d4 2025-06-25 xs }
1759 8e44e3d4 2025-06-25 xs
1760 8e44e3d4 2025-06-25 xs _DragonFly_import() {
1761 8e44e3d4 2025-06-25 xs etc_files_to_import='
1762 8e44e3d4 2025-06-25 xs crontab
1763 8e44e3d4 2025-06-25 xs fstab
1764 8e44e3d4 2025-06-25 xs hosts
1765 8e44e3d4 2025-06-25 xs login.conf
1766 8e44e3d4 2025-06-25 xs pf.conf
1767 8e44e3d4 2025-06-25 xs resolv.conf
1768 8e44e3d4 2025-06-25 xs shells
1769 8e44e3d4 2025-06-25 xs sysctl.conf
1770 8e44e3d4 2025-06-25 xs syslog.conf
1771 8e44e3d4 2025-06-25 xs '
1772 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1773 8e44e3d4 2025-06-25 xs _import_etc_ssh_if_exists
1774 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1775 8e44e3d4 2025-06-25 xs }
1776 8e44e3d4 2025-06-25 xs
1777 8e44e3d4 2025-06-25 xs _NetBSD_import() {
1778 8e44e3d4 2025-06-25 xs etc_files_to_import='
1779 8e44e3d4 2025-06-25 xs fstab
1780 8e44e3d4 2025-06-25 xs hosts
1781 8e44e3d4 2025-06-25 xs locate.conf
1782 8e44e3d4 2025-06-25 xs pf.conf
1783 8e44e3d4 2025-06-25 xs resolv.conf
1784 8e44e3d4 2025-06-25 xs shells
1785 8e44e3d4 2025-06-25 xs sysctl.conf
1786 8e44e3d4 2025-06-25 xs syslog.conf
1787 8e44e3d4 2025-06-25 xs usermgmt.conf
1788 8e44e3d4 2025-06-25 xs wscons.conf
1789 8e44e3d4 2025-06-25 xs rc.local
1790 8e44e3d4 2025-06-25 xs '
1791 8e44e3d4 2025-06-25 xs _import_etc_if_exists
1792 8e44e3d4 2025-06-25 xs _import_etc_ssh_if_exists
1793 8e44e3d4 2025-06-25 xs _import_ssh_authorized_keys
1794 8e44e3d4 2025-06-25 xs }
1795 8e44e3d4 2025-06-25 xs
1796 a4759196 2025-06-13 xs _OpenBSD_import() {
1797 a4759196 2025-06-13 xs etc_files_to_import='
1798 730e151b 2025-06-02 xs acme-client.conf
1799 a4759196 2025-06-13 xs boot.conf
1800 730e151b 2025-06-02 xs dhcpcd.conf
1801 a4759196 2025-06-13 xs dhcpd.conf
1802 730e151b 2025-06-02 xs doas.conf
1803 730e151b 2025-06-02 xs fstab
1804 a4759196 2025-06-13 xs gotd.conf
1805 a4759196 2025-06-13 xs gotwebd.conf
1806 730e151b 2025-06-02 xs hosts
1807 730e151b 2025-06-02 xs httpd.conf
1808 730e151b 2025-06-02 xs installurl
1809 a4759196 2025-06-13 xs locate.rc
1810 730e151b 2025-06-02 xs login.conf
1811 730e151b 2025-06-02 xs mygate
1812 730e151b 2025-06-02 xs myname
1813 a4759196 2025-06-13 xs newsyslog.conf
1814 8e44e3d4 2025-06-25 xs syslog.conf
1815 730e151b 2025-06-02 xs ntpd.conf
1816 730e151b 2025-06-02 xs pf.conf
1817 a4759196 2025-06-13 xs resolv.conf
1818 730e151b 2025-06-02 xs sysctl.conf
1819 730e151b 2025-06-02 xs unwind.conf
1820 a4759196 2025-06-13 xs usermgt.conf
1821 8e44e3d4 2025-06-25 xs rc.conf.local
1822 730e151b 2025-06-02 xs '
1823 730e151b 2025-06-02 xs etc_ssh_files_to_import='
1824 730e151b 2025-06-02 xs ssh/sshd_config
1825 730e151b 2025-06-02 xs ssh/ssh_config
1826 730e151b 2025-06-02 xs '
1827 730e151b 2025-06-02 xs var_unbound_files='
1828 730e151b 2025-06-02 xs db/named.root
1829 730e151b 2025-06-02 xs etc/unbound.conf
1830 730e151b 2025-06-02 xs '
1831 730e151b 2025-06-02 xs var_nsd_files='
1832 730e151b 2025-06-02 xs etc/nsd.conf
1833 730e151b 2025-06-02 xs '
1834 730e151b 2025-06-02 xs var_postgresql_files='
1835 730e151b 2025-06-02 xs data/pg_hba.conf
1836 730e151b 2025-06-02 xs data/postgresql.conf
1837 730e151b 2025-06-02 xs '
1838 a4759196 2025-06-13 xs _import_ssh_authorized_keys
1839 a4759196 2025-06-13 xs _OpenBSD_import_etc_if_exists
1840 a4759196 2025-06-13 xs _import_etc_ssh_if_exists
1841 a4759196 2025-06-13 xs _OpenBSD_import_etc_mail_if_exists
1842 a4759196 2025-06-13 xs _OpenBSD_import_unbound_if_enabled
1843 a4759196 2025-06-13 xs _OpenBSD_import_nsd_if_enabled
1844 a4759196 2025-06-13 xs _OpenBSD_import_postgresql_if_installed
1845 730e151b 2025-06-02 xs }
1846 730e151b 2025-06-02 xs
1847 d8747c12 2025-06-03 xs _OpenBSD_import_etc_if_exists() {
1848 730e151b 2025-06-02 xs mkdir -p nodes/"$target"
1849 730e151b 2025-06-02 xs interfaces=$(ssh "$target" 'cd /etc && ls -1 hostname.*')
1850 730e151b 2025-06-02 xs echo >&2 "--> Importing /etc"
1851 730e151b 2025-06-02 xs for file in $etc_files_to_import $interfaces; do
1852 730e151b 2025-06-02 xs ssh "$target" test -f "'/etc/$file'" &&
1853 d8747c12 2025-06-03 xs _import_copy "$target:/etc/$file" "nodes/$target/"
1854 730e151b 2025-06-02 xs done
1855 730e151b 2025-06-02 xs }
1856 730e151b 2025-06-02 xs
1857 519b84c4 2025-06-05 xs _OpenBSD_import_etc_mail_if_exists() {
1858 8e44e3d4 2025-06-25 xs etc_mail_files_to_import='
1859 8e44e3d4 2025-06-25 xs mail/aliases
1860 8e44e3d4 2025-06-25 xs mail/smtpd.conf
1861 8e44e3d4 2025-06-25 xs mail/spamd.conf
1862 8e44e3d4 2025-06-25 xs '
1863 519b84c4 2025-06-05 xs mkdir -p nodes/"$target"
1864 1a4cdaf8 2025-06-05 xs echo >&2 "--> Importing /etc/mail"
1865 519b84c4 2025-06-05 xs for file in $etc_mail_files_to_import; do
1866 519b84c4 2025-06-05 xs ssh "$target" test -f "'/etc/$file'" &&
1867 519b84c4 2025-06-05 xs _import_copy "$target:/etc/$file" "nodes/$target/mail"
1868 519b84c4 2025-06-05 xs done
1869 519b84c4 2025-06-05 xs }
1870 519b84c4 2025-06-05 xs
1871 d8747c12 2025-06-03 xs _OpenBSD_import_unbound_if_enabled() {
1872 730e151b 2025-06-02 xs ssh "$target" rcctl check unbound >/dev/null && {
1873 730e151b 2025-06-02 xs echo >&2 "--> Importing /var/unbound"
1874 730e151b 2025-06-02 xs for file in $var_unbound_files; do
1875 730e151b 2025-06-02 xs prefix=${file%%/*}
1876 730e151b 2025-06-02 xs mkdir -p "nodes/$target/unbound/$prefix"
1877 d8747c12 2025-06-03 xs _import_copy "$target:/var/unbound/$file" "nodes/$target/unbound/$prefix/"
1878 730e151b 2025-06-02 xs done
1879 730e151b 2025-06-02 xs return 0
1880 730e151b 2025-06-02 xs }
1881 730e151b 2025-06-02 xs }
1882 730e151b 2025-06-02 xs
1883 d8747c12 2025-06-03 xs _OpenBSD_import_nsd_if_enabled() {
1884 730e151b 2025-06-02 xs ssh "$target" rcctl check nsd >/dev/null && {
1885 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /var/nsd"
1886 730e151b 2025-06-02 xs for file in $var_nsd_files; do
1887 730e151b 2025-06-02 xs prefix=${file%%/*}
1888 730e151b 2025-06-02 xs mkdir -p "nodes/$target/nsd/$prefix"
1889 d8747c12 2025-06-03 xs _import_copy "$target:/var/nsd/$file" "nodes/$target/nsd/$prefix/"
1890 730e151b 2025-06-02 xs done
1891 730e151b 2025-06-02 xs return 0
1892 730e151b 2025-06-02 xs }
1893 730e151b 2025-06-02 xs }
1894 730e151b 2025-06-02 xs
1895 d8747c12 2025-06-03 xs _OpenBSD_import_postgresql_if_installed() {
1896 730e151b 2025-06-02 xs ssh "$target" postgres -V 2>/dev/null | grep -q PostgreSQL && {
1897 730e151b 2025-06-02 xs echo >&2 "--> Importing /var/postgresql"
1898 730e151b 2025-06-02 xs for file in $var_postgresql_files; do
1899 730e151b 2025-06-02 xs prefix=${file%%/*}
1900 730e151b 2025-06-02 xs mkdir -p "nodes/$target/postgresql/$prefix"
1901 d8747c12 2025-06-03 xs _import_copy "$target:/var/postgresql/$file" "nodes/$target/postgresql/$prefix/"
1902 730e151b 2025-06-02 xs done
1903 8e44e3d4 2025-06-25 xs echo >&2 "--> Importing /etc/login.conf.d/postgresql"
1904 730e151b 2025-06-02 xs mkdir -p "nodes/$target/login.conf.d"
1905 d8747c12 2025-06-03 xs _import_copy "$target:/etc/login.conf.d/postgresql" "nodes/$target/login.conf.d/"
1906 730e151b 2025-06-02 xs return 0
1907 730e151b 2025-06-02 xs }
1908 730e151b 2025-06-02 xs }
1909 730e151b 2025-06-02 xs
1910 03d8f521 2025-05-27 xs # Main
1911 03d8f521 2025-05-27 xs # ====
1912 03d8f521 2025-05-27 xs
1913 46924c01 2025-05-28 xs _main "${@:-}"