-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathstep_shell.go
More file actions
133 lines (110 loc) · 2.86 KB
/
step_shell.go
File metadata and controls
133 lines (110 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package hrp
import (
"fmt"
"os"
"time"
"github.com/httprunner/funplugin/myexec"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
type Shell struct {
String string `json:"string" yaml:"string"`
ExpectExitCode int `json:"expect_exit_code" yaml:"expect_exit_code"`
}
// StepShell implements IStep interface.
type StepShell struct {
StepConfig
Shell *Shell `json:"shell,omitempty" yaml:"shell,omitempty"`
}
func (s *StepShell) Name() string {
return s.StepName
}
func (s *StepShell) Type() StepType {
return StepTypeShell
}
func (s *StepShell) Config() *StepConfig {
return &s.StepConfig
}
func (s *StepShell) Run(r *SessionRunner) (*StepResult, error) {
return runStepShell(r, s)
}
// Validate switches to step validation.
func (s *StepShell) Validate() *StepShellValidation {
return &StepShellValidation{
StepConfig: s.StepConfig,
Shell: s.Shell,
}
}
// StepShellValidation implements IStep interface.
type StepShellValidation struct {
StepConfig
Shell *Shell `json:"shell,omitempty" yaml:"shell,omitempty"`
}
func (s *StepShellValidation) Name() string {
return s.StepName
}
func (s *StepShellValidation) Type() StepType {
return StepTypeShell + stepTypeSuffixValidation
}
func (s *StepShellValidation) Config() *StepConfig {
return &s.StepConfig
}
func (s *StepShellValidation) Run(r *SessionRunner) (*StepResult, error) {
return runStepShell(r, s)
}
func (s *StepShellValidation) AssertExitCode(expected int) *StepShellValidation {
s.Shell.ExpectExitCode = expected
return s
}
func runStepShell(r *SessionRunner, step IStep) (stepResult *StepResult, err error) {
var shell *Shell
switch stepShell := step.(type) {
case *StepShell:
shell = stepShell.Shell
case *StepShellValidation:
shell = stepShell.Shell
default:
return nil, errors.New("invalid shell step type")
}
log.Info().
Str("name", step.Name()).
Str("type", string(step.Type())).
Str("content", shell.String).
Msg("run shell string")
start := time.Now()
stepResult = &StepResult{
Name: step.Name(),
StepType: step.Type(),
Success: false,
ContentSize: 0,
StartTime: start.UnixMilli(),
}
defer func() {
stepResult.Elapsed = time.Since(start).Milliseconds()
}()
vars := r.caseRunner.Config.Get().Variables
for key, value := range vars {
os.Setenv(key, fmt.Sprintf("%v", value))
}
exitCode, err := myexec.RunShell(shell.String)
if err != nil {
if exitCode == shell.ExpectExitCode {
// get expected error
log.Warn().Err(err).
Int("exitCode", exitCode).
Msg("get expected error, ignore")
stepResult.Success = true
return stepResult, nil
}
err = errors.Wrap(err, "exec shell string failed")
return
}
// validate response
if exitCode != shell.ExpectExitCode {
err = fmt.Errorf("unexpected exit code %d, expect %d",
exitCode, shell.ExpectExitCode)
return
}
stepResult.Success = true
return stepResult, nil
}