Skip to content

Commit 47677cb

Browse files
subprocess Add support for overriding the stdin/stdout/stderr of a process when running it with subprocess.Execute (#706)
<!-- Copyright (C) 2020-2022 Arm Limited or its affiliates and Contributors. All rights reserved. SPDX-License-Identifier: Apache-2.0 --> ### Description <!-- Please add any detail or context that would be useful to a reviewer. --> Add support for overriding the stdin/stdout/stderr of a process when running it with subprocess.Execute ### Test Coverage <!-- Please put an `x` in the correct box e.g. `[x]` to indicate the testing coverage of this change. --> - [x] This change is covered by existing or additional automated tests. - [ ] Manual testing has been performed (and evidence provided) as automated testing was not feasible. - [ ] Additional tests are not required for this change (e.g. documentation update).
1 parent e0f5dc3 commit 47677cb

File tree

2 files changed

+48
-12
lines changed

2 files changed

+48
-12
lines changed

changes/20250911130716.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:sparkles: `subprocess` Add support for overriding the stdin/stdout/stderr of a process when running it with subprocess.Execute

utils/subprocess/executor.go

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,22 @@ func New(ctx context.Context, loggers logs.Loggers, messageOnStart string, messa
3434

3535
// NewWithEnvironment creates a subprocess description. It allows to specify the environment the subprocess should use. Each entry is of the form "key=value".
3636
func NewWithEnvironment(ctx context.Context, loggers logs.Loggers, additionalEnvVars []string, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) (p *Subprocess, err error) {
37-
p, err = newSubProcess(ctx, loggers, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, commandUtils.Me(), cmd, args...)
37+
return NewWithEnvironmentWithIO(ctx, loggers, nil, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, cmd, args...)
38+
}
39+
40+
// NewWithIO creates a subprocess description with overridden stdin/stdout/stderr.
41+
func NewWithIO(ctx context.Context, loggers logs.Loggers, io ICommandIO, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) (*Subprocess, error) {
42+
return NewWithEnvironmentWithIO(ctx, loggers, io, nil, messageOnStart, messageOnSuccess, messageOnFailure, cmd, args...)
43+
}
44+
45+
// NewWithEnvironmentWithIO creates a subprocess description with overridden stdin/stdout/stderr. It allows to specify the environment the subprocess should use. Each entry is of the form "key=value".
46+
func NewWithEnvironmentWithIO(ctx context.Context, loggers logs.Loggers, io ICommandIO, additionalEnvVars []string, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) (p *Subprocess, err error) {
47+
p, err = newSubProcess(ctx, loggers, io, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, commandUtils.Me(), cmd, args...)
3848
return
3949
}
4050

41-
// newSubProcess creates a subprocess description.
42-
func newSubProcess(ctx context.Context, loggers logs.Loggers, env []string, messageOnStart string, messageOnSuccess, messageOnFailure string, as *commandUtils.CommandAsDifferentUser, cmd string, args ...string) (p *Subprocess, err error) {
51+
// newSubProcess creates a subprocess description with custom IO
52+
func newSubProcess(ctx context.Context, loggers logs.Loggers, io ICommandIO, env []string, messageOnStart string, messageOnSuccess, messageOnFailure string, as *commandUtils.CommandAsDifferentUser, cmd string, args ...string) (p *Subprocess, err error) {
4353
p = new(Subprocess)
4454
err = p.SetupAsWithEnvironment(ctx, loggers, env, messageOnStart, messageOnSuccess, messageOnFailure, as, cmd, args...)
4555
return
@@ -53,11 +63,7 @@ func newPlainSubProcess(ctx context.Context, loggers logs.Loggers, env []string,
5363

5464
// ExecuteWithEnvironment executes a command (i.e. spawns a subprocess). It allows to specify the environment the subprocess should use. Each entry is of the form "key=value".
5565
func ExecuteWithEnvironment(ctx context.Context, loggers logs.Loggers, additionalEnvVars []string, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) (err error) {
56-
p, err := NewWithEnvironment(ctx, loggers, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, cmd, args...)
57-
if err != nil {
58-
return
59-
}
60-
return p.Execute()
66+
return ExecuteWithEnvironmentWithIO(ctx, loggers, nil, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, cmd, args...)
6167
}
6268

6369
// Execute executes a command (i.e. spawns a subprocess).
@@ -72,16 +78,45 @@ func ExecuteAs(ctx context.Context, loggers logs.Loggers, messageOnStart string,
7278

7379
// ExecuteAsWithEnvironment executes a command (i.e. spawns a subprocess) as a different user. It allows to specify the environment the subprocess should use. Each entry is of the form "key=value".
7480
func ExecuteAsWithEnvironment(ctx context.Context, loggers logs.Loggers, additionalEnvVars []string, messageOnStart string, messageOnSuccess, messageOnFailure string, as *commandUtils.CommandAsDifferentUser, cmd string, args ...string) (err error) {
75-
p, err := newSubProcess(ctx, loggers, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, as, cmd, args...)
81+
return ExecuteAsWithEnvironmentWithIO(ctx, loggers, nil, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, as, cmd, args...)
82+
}
83+
84+
// ExecuteWithSudo executes a command (i.e. spawns a subprocess) as root.
85+
func ExecuteWithSudo(ctx context.Context, loggers logs.Loggers, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) error {
86+
return ExecuteAs(ctx, loggers, messageOnStart, messageOnSuccess, messageOnFailure, commandUtils.Sudo(), cmd, args...)
87+
}
88+
89+
// ExecuteWithEnvironment executes a command (i.e. spawns a subprocess) with overridden stdin/stdout/stderr. It allows to specify the environment the subprocess should use. Each entry is of the form "key=value".
90+
func ExecuteWithEnvironmentWithIO(ctx context.Context, loggers logs.Loggers, io ICommandIO, additionalEnvVars []string, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) (err error) {
91+
p, err := NewWithEnvironmentWithIO(ctx, loggers, io, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, cmd, args...)
7692
if err != nil {
7793
return
7894
}
7995
return p.Execute()
8096
}
8197

82-
// ExecuteWithSudo executes a command (i.e. spawns a subprocess) as root.
83-
func ExecuteWithSudo(ctx context.Context, loggers logs.Loggers, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) error {
84-
return ExecuteAs(ctx, loggers, messageOnStart, messageOnSuccess, messageOnFailure, commandUtils.Sudo(), cmd, args...)
98+
// ExecuteWithIO executes a command (i.e. spawns a subprocess) with overridden stdin/stdout/stderr.
99+
func ExecuteWithIO(ctx context.Context, loggers logs.Loggers, io ICommandIO, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) error {
100+
return ExecuteWithEnvironmentWithIO(ctx, loggers, io, nil, messageOnStart, messageOnSuccess, messageOnFailure, cmd, args...)
101+
}
102+
103+
// ExecuteAsWithIO executes a command (i.e. spawns a subprocess) as a different user with overridden stdin/stdout/stderr.
104+
func ExecuteAsWithIO(ctx context.Context, loggers logs.Loggers, io ICommandIO, messageOnStart string, messageOnSuccess, messageOnFailure string, as *commandUtils.CommandAsDifferentUser, cmd string, args ...string) error {
105+
return ExecuteAsWithEnvironmentWithIO(ctx, loggers, io, nil, messageOnStart, messageOnSuccess, messageOnFailure, as, cmd, args...)
106+
}
107+
108+
// ExecuteAsWithEnvironmentWithIO executes a command (i.e. spawns a subprocess) as a different user with overridden stdin/stdout/stderr. It allows to specify the environment the subprocess should use. Each entry is of the form "key=value".
109+
func ExecuteAsWithEnvironmentWithIO(ctx context.Context, loggers logs.Loggers, io ICommandIO, additionalEnvVars []string, messageOnStart string, messageOnSuccess, messageOnFailure string, as *commandUtils.CommandAsDifferentUser, cmd string, args ...string) (err error) {
110+
p, err := newSubProcess(ctx, loggers, io, additionalEnvVars, messageOnStart, messageOnSuccess, messageOnFailure, as, cmd, args...)
111+
if err != nil {
112+
return
113+
}
114+
return p.Execute()
115+
}
116+
117+
// ExecuteWithSudoWithIO executes a command (i.e. spawns a subprocess) as root with overridden stdin/stdout/stderr.
118+
func ExecuteWithSudoWithIO(ctx context.Context, loggers logs.Loggers, io ICommandIO, messageOnStart string, messageOnSuccess, messageOnFailure string, cmd string, args ...string) error {
119+
return ExecuteAsWithIO(ctx, loggers, io, messageOnStart, messageOnSuccess, messageOnFailure, commandUtils.Sudo(), cmd, args...)
85120
}
86121

87122
// Output executes a command and returns its output (stdOutput and stdErr are merged) as string.

0 commit comments

Comments
 (0)