@@ -61,20 +61,52 @@ func Eval(t testing.TestingT, options *EvalOptions, jsonFilePaths []string, resu
61
61
// opa eval -i $JSONFile -d $RulePath $ResultQuery
62
62
//
63
63
// This will asynchronously run OPA on each file concurrently using goroutines.
64
- func EvalE (t testing.TestingT , options * EvalOptions , jsonFilePaths []string , resultQuery string ) error {
64
+ // This will fail the test if any one of the files failed.
65
+ // For each file, the output will be returned on the outputs slice.
66
+ func EvalWithOutput (t testing.TestingT , options * EvalOptions , jsonFilePaths []string , resultQuery string ) (outputs []string ) {
67
+ outputs , err := EvalWithOutputE (t , options , jsonFilePaths , resultQuery )
68
+ require .NoError (t , err )
69
+ return
70
+ }
71
+
72
+ // EvalE runs `opa eval` on the given JSON files using the configured policy file and result query. Translates to:
73
+ //
74
+ // opa eval -i $JSONFile -d $RulePath $ResultQuery
75
+ //
76
+ // This will asynchronously run OPA on each file concurrently using goroutines.
77
+ func EvalE (t testing.TestingT , options * EvalOptions , jsonFilePaths []string , resultQuery string ) (err error ) {
78
+ _ , err = evalE (t , options , jsonFilePaths , resultQuery )
79
+ return
80
+ }
81
+
82
+ // EvalWithOutputE runs `opa eval` on the given JSON files using the configured policy file and result query. Translates to:
83
+ //
84
+ // opa eval -i $JSONFile -d $RulePath $ResultQuery
85
+ //
86
+ // This will asynchronously run OPA on each file concurrently using goroutines.
87
+ // For each file, the output will be returned on the outputs slice.
88
+ func EvalWithOutputE (t testing.TestingT , options * EvalOptions , jsonFilePaths []string , resultQuery string ) (outputs []string , err error ) {
89
+ return evalE (t , options , jsonFilePaths , resultQuery )
90
+ }
91
+
92
+ func evalE (t testing.TestingT , options * EvalOptions , jsonFilePaths []string , resultQuery string ) (outputs []string , err error ) {
65
93
downloadedPolicyPath , err := DownloadPolicyE (t , options .RulePath )
66
94
if err != nil {
67
- return err
95
+ return
68
96
}
69
97
98
+ outputs = make ([]string , len (jsonFilePaths ))
70
99
wg := new (sync.WaitGroup )
71
100
wg .Add (len (jsonFilePaths ))
72
101
errorsOccurred := new (multierror.Error )
73
102
errChans := make ([]chan error , len (jsonFilePaths ))
74
103
for i , jsonFilePath := range jsonFilePaths {
75
104
errChan := make (chan error , 1 )
76
105
errChans [i ] = errChan
77
- go asyncEval (t , wg , errChan , options , downloadedPolicyPath , jsonFilePath , resultQuery )
106
+
107
+ go func (i int , jsonFilePath string ) {
108
+ outputs [i ] = asyncEval (t , wg , errChan , options , downloadedPolicyPath , jsonFilePath , resultQuery )
109
+ }(i , jsonFilePath )
78
110
}
79
111
wg .Wait ()
80
112
for _ , errChan := range errChans {
@@ -83,7 +115,7 @@ func EvalE(t testing.TestingT, options *EvalOptions, jsonFilePaths []string, res
83
115
errorsOccurred = multierror .Append (errorsOccurred , err )
84
116
}
85
117
}
86
- return errorsOccurred .ErrorOrNil ()
118
+ return outputs , errorsOccurred .ErrorOrNil ()
87
119
}
88
120
89
121
// asyncEval is a function designed to be run in a goroutine to asynchronously call `opa eval` on a single input file.
@@ -95,7 +127,7 @@ func asyncEval(
95
127
downloadedPolicyPath string ,
96
128
jsonFilePath string ,
97
129
resultQuery string ,
98
- ) {
130
+ ) ( output string ) {
99
131
defer wg .Done ()
100
132
cmd := shell.Command {
101
133
Command : "opa" ,
@@ -105,7 +137,7 @@ func asyncEval(
105
137
// opa eval is typically very quick.
106
138
Logger : logger .Discard ,
107
139
}
108
- err := runCommandWithFullLoggingE (t , options .Logger , cmd )
140
+ output , err := runCommandWithFullLoggingE (t , options .Logger , cmd )
109
141
ruleBasePath := filepath .Base (downloadedPolicyPath )
110
142
if err == nil {
111
143
options .Logger .Logf (t , "opa eval passed on file %s (policy %s; query %s)" , jsonFilePath , ruleBasePath , resultQuery )
@@ -115,10 +147,12 @@ func asyncEval(
115
147
options .Logger .Logf (t , "DEBUG: rerunning opa eval to query for full data." )
116
148
cmd .Args = formatOPAEvalArgs (options , downloadedPolicyPath , jsonFilePath , "data" )
117
149
// We deliberately ignore the error here as we want to only return the original error.
118
- runCommandWithFullLoggingE (t , options .Logger , cmd )
150
+ output , _ = runCommandWithFullLoggingE (t , options .Logger , cmd )
119
151
}
120
152
}
121
153
errChan <- err
154
+
155
+ return
122
156
}
123
157
124
158
// formatOPAEvalArgs formats the arguments for the `opa eval` command.
@@ -146,8 +180,8 @@ func formatOPAEvalArgs(options *EvalOptions, rulePath, jsonFilePath, resultQuery
146
180
// runCommandWithFullLogging will log the command output in its entirety with buffering. This avoids breaking up the
147
181
// logs when commands are run concurrently. This is a private function used in the context of opa only because opa runs
148
182
// very quickly, and the output of opa is hard to parse if it is broken up by interleaved logs.
149
- func runCommandWithFullLoggingE (t testing.TestingT , logger * logger.Logger , cmd shell.Command ) error {
150
- output , err : = shell .RunCommandAndGetOutputE (t , cmd )
183
+ func runCommandWithFullLoggingE (t testing.TestingT , logger * logger.Logger , cmd shell.Command ) ( output string , err error ) {
184
+ output , err = shell .RunCommandAndGetOutputE (t , cmd )
151
185
logger .Logf (t , "Output of command `%s %s`:\n %s" , cmd .Command , strings .Join (cmd .Args , " " ), output )
152
- return err
186
+ return
153
187
}
0 commit comments