Merge pull request #167838 from tljuniper/test-driver-pipefail-fix

nixos/test-driver: shellopts with execute + timeout

authored by Jacek Galowicz and committed by GitHub 2656cb99 ab83c5d7

+87 -51
+25 -14
nixos/doc/manual/development/writing-nixos-tests.section.md
··· 159 `execute` 160 161 : Execute a shell command, returning a list `(status, stdout)`. 162 If the command detaches, it must close stdout, as `execute` will wait 163 for this to consume all output reliably. This can be achieved by 164 redirecting stdout to stderr `>&2`, to `/dev/console`, `/dev/null` or 165 a file. Examples of detaching commands are `sleep 365d &`, where the 166 shell forks a new process that can write to stdout and `xclip -i`, where 167 the `xclip` command itself forks without closing stdout. 168 Takes an optional parameter `check_return` that defaults to `True`. 169 Setting this parameter to `False` will not check for the return code 170 and return -1 instead. This can be used for commands that shut down 171 the VM and would therefore break the pipe that would be used for 172 retrieving the return code. 173 174 `succeed` 175 176 : Execute a shell command, raising an exception if the exit status is 177 - not zero, otherwise returning the standard output. Commands are run 178 - with `set -euo pipefail` set: 179 - 180 - - If several commands are separated by `;` and one fails, the 181 - command as a whole will fail. 182 - 183 - - For pipelines, the last non-zero exit status will be returned 184 - (if there is one, zero will be returned otherwise). 185 - 186 - - Dereferencing unset variables fail the command. 187 - 188 - - It will wait for stdout to be closed. See `execute` for the 189 - implications. 190 191 `fail` 192 ··· 196 `wait_until_succeeds` 197 198 : Repeat a shell command with 1-second intervals until it succeeds. 199 200 `wait_until_fails` 201 202 - : Repeat a shell command with 1-second intervals until it fails. 203 204 `wait_for_unit` 205
··· 159 `execute` 160 161 : Execute a shell command, returning a list `(status, stdout)`. 162 + 163 + Commands are run with `set -euo pipefail` set: 164 + 165 + - If several commands are separated by `;` and one fails, the 166 + command as a whole will fail. 167 + 168 + - For pipelines, the last non-zero exit status will be returned 169 + (if there is one; otherwise zero will be returned). 170 + 171 + - Dereferencing unset variables fails the command. 172 + 173 + - It will wait for stdout to be closed. 174 + 175 If the command detaches, it must close stdout, as `execute` will wait 176 for this to consume all output reliably. This can be achieved by 177 redirecting stdout to stderr `>&2`, to `/dev/console`, `/dev/null` or 178 a file. Examples of detaching commands are `sleep 365d &`, where the 179 shell forks a new process that can write to stdout and `xclip -i`, where 180 the `xclip` command itself forks without closing stdout. 181 + 182 Takes an optional parameter `check_return` that defaults to `True`. 183 Setting this parameter to `False` will not check for the return code 184 and return -1 instead. This can be used for commands that shut down 185 the VM and would therefore break the pipe that would be used for 186 retrieving the return code. 187 188 + A timeout for the command can be specified (in seconds) using the optional 189 + `timeout` parameter, e.g., `execute(cmd, timeout=10)` or 190 + `execute(cmd, timeout=None)`. The default is 900 seconds. 191 + 192 `succeed` 193 194 : Execute a shell command, raising an exception if the exit status is 195 + not zero, otherwise returning the standard output. Similar to `execute`, 196 + except that the timeout is `None` by default. See `execute` for details on 197 + command execution. 198 199 `fail` 200 ··· 204 `wait_until_succeeds` 205 206 : Repeat a shell command with 1-second intervals until it succeeds. 207 + Has a default timeout of 900 seconds which can be modified, e.g. 208 + `wait_until_succeeds(cmd, timeout=10)`. See `execute` for details on 209 + command execution. 210 211 `wait_until_fails` 212 213 + : Like `wait_until_succeeds`, but repeating the command until it fails. 214 215 `wait_for_unit` 216
+53 -35
nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml
··· 274 <listitem> 275 <para> 276 Execute a shell command, returning a list 277 - <literal>(status, stdout)</literal>. If the command 278 - detaches, it must close stdout, as 279 - <literal>execute</literal> will wait for this to consume all 280 - output reliably. This can be achieved by redirecting stdout 281 - to stderr <literal>&gt;&amp;2</literal>, to 282 - <literal>/dev/console</literal>, 283 - <literal>/dev/null</literal> or a file. Examples of 284 - detaching commands are <literal>sleep 365d &amp;</literal>, 285 - where the shell forks a new process that can write to stdout 286 - and <literal>xclip -i</literal>, where the 287 - <literal>xclip</literal> command itself forks without 288 - closing stdout. Takes an optional parameter 289 - <literal>check_return</literal> that defaults to 290 - <literal>True</literal>. Setting this parameter to 291 - <literal>False</literal> will not check for the return code 292 - and return -1 instead. This can be used for commands that 293 - shut down the VM and would therefore break the pipe that 294 - would be used for retrieving the return code. 295 </para> 296 - </listitem> 297 - </varlistentry> 298 - <varlistentry> 299 - <term> 300 - <literal>succeed</literal> 301 - </term> 302 - <listitem> 303 <para> 304 - Execute a shell command, raising an exception if the exit 305 - status is not zero, otherwise returning the standard output. 306 Commands are run with <literal>set -euo pipefail</literal> 307 set: 308 </para> ··· 317 <listitem> 318 <para> 319 For pipelines, the last non-zero exit status will be 320 - returned (if there is one, zero will be returned 321 - otherwise). 322 </para> 323 </listitem> 324 <listitem> 325 <para> 326 - Dereferencing unset variables fail the command. 327 </para> 328 </listitem> 329 <listitem> 330 <para> 331 - It will wait for stdout to be closed. See 332 - <literal>execute</literal> for the implications. 333 </para> 334 </listitem> 335 </itemizedlist> 336 </listitem> 337 </varlistentry> 338 <varlistentry> ··· 353 <listitem> 354 <para> 355 Repeat a shell command with 1-second intervals until it 356 - succeeds. 357 </para> 358 </listitem> 359 </varlistentry> ··· 363 </term> 364 <listitem> 365 <para> 366 - Repeat a shell command with 1-second intervals until it 367 - fails. 368 </para> 369 </listitem> 370 </varlistentry>
··· 274 <listitem> 275 <para> 276 Execute a shell command, returning a list 277 + <literal>(status, stdout)</literal>. 278 </para> 279 <para> 280 Commands are run with <literal>set -euo pipefail</literal> 281 set: 282 </para> ··· 291 <listitem> 292 <para> 293 For pipelines, the last non-zero exit status will be 294 + returned (if there is one; otherwise zero will be 295 + returned). 296 </para> 297 </listitem> 298 <listitem> 299 <para> 300 + Dereferencing unset variables fails the command. 301 </para> 302 </listitem> 303 <listitem> 304 <para> 305 + It will wait for stdout to be closed. 306 </para> 307 </listitem> 308 </itemizedlist> 309 + <para> 310 + If the command detaches, it must close stdout, as 311 + <literal>execute</literal> will wait for this to consume all 312 + output reliably. This can be achieved by redirecting stdout 313 + to stderr <literal>&gt;&amp;2</literal>, to 314 + <literal>/dev/console</literal>, 315 + <literal>/dev/null</literal> or a file. Examples of 316 + detaching commands are <literal>sleep 365d &amp;</literal>, 317 + where the shell forks a new process that can write to stdout 318 + and <literal>xclip -i</literal>, where the 319 + <literal>xclip</literal> command itself forks without 320 + closing stdout. 321 + </para> 322 + <para> 323 + Takes an optional parameter <literal>check_return</literal> 324 + that defaults to <literal>True</literal>. Setting this 325 + parameter to <literal>False</literal> will not check for the 326 + return code and return -1 instead. This can be used for 327 + commands that shut down the VM and would therefore break the 328 + pipe that would be used for retrieving the return code. 329 + </para> 330 + <para> 331 + A timeout for the command can be specified (in seconds) 332 + using the optional <literal>timeout</literal> parameter, 333 + e.g., <literal>execute(cmd, timeout=10)</literal> or 334 + <literal>execute(cmd, timeout=None)</literal>. The default 335 + is 900 seconds. 336 + </para> 337 + </listitem> 338 + </varlistentry> 339 + <varlistentry> 340 + <term> 341 + <literal>succeed</literal> 342 + </term> 343 + <listitem> 344 + <para> 345 + Execute a shell command, raising an exception if the exit 346 + status is not zero, otherwise returning the standard output. 347 + Similar to <literal>execute</literal>, except that the 348 + timeout is <literal>None</literal> by default. See 349 + <literal>execute</literal> for details on command execution. 350 + </para> 351 </listitem> 352 </varlistentry> 353 <varlistentry> ··· 368 <listitem> 369 <para> 370 Repeat a shell command with 1-second intervals until it 371 + succeeds. Has a default timeout of 900 seconds which can be 372 + modified, e.g. 373 + <literal>wait_until_succeeds(cmd, timeout=10)</literal>. See 374 + <literal>execute</literal> for details on command execution. 375 </para> 376 </listitem> 377 </varlistentry> ··· 381 </term> 382 <listitem> 383 <para> 384 + Like <literal>wait_until_succeeds</literal>, but repeating 385 + the command until it fails. 386 </para> 387 </listitem> 388 </varlistentry>
+9 -2
nixos/lib/test-driver/test_driver/machine.py
··· 526 self.run_callbacks() 527 self.connect() 528 529 if timeout is not None: 530 - command = "timeout {} sh -c {}".format(timeout, shlex.quote(command)) 531 532 - out_command = f"( set -euo pipefail; {command} ) | (base64 --wrap 0; echo)\n" 533 assert self.shell 534 self.shell.send(out_command.encode()) 535
··· 526 self.run_callbacks() 527 self.connect() 528 529 + # Always run command with shell opts 530 + command = f"set -euo pipefail; {command}" 531 + 532 + timeout_str = "" 533 if timeout is not None: 534 + timeout_str = f"timeout {timeout}" 535 + 536 + out_command = ( 537 + f"{timeout_str} sh -c {shlex.quote(command)} | (base64 --wrap 0; echo)\n" 538 + ) 539 540 assert self.shell 541 self.shell.send(out_command.encode()) 542