@@ -10,6 +10,7 @@ import (
1010 "io"
1111 "net"
1212 "os"
13+ "os/exec"
1314 "os/signal"
1415 "path/filepath"
1516 "runtime"
@@ -30,8 +31,9 @@ import (
3031)
3132
3233const (
33- summaryListenAddr = "127.0.0.1:0"
34- FeaturePassed = "PASSED"
34+ proxyExecutableAuto = "auto"
35+ freePortListenAddr = "127.0.0.1:0"
36+ FeaturePassed = "PASSED"
3537)
3638
3739func runCmd () * cli.Command {
@@ -66,6 +68,40 @@ type RunConfig struct {
6668 RetainTempDir bool
6769 SummaryURI string
6870 HTTPProxyURL string
71+ ProxyControlURI string
72+ ProxyListenHostPort string
73+ }
74+
75+ func (config RunConfig ) appendFlags (out []string ) ([]string , error ) {
76+ out = append (out , "--server=" + config .Server )
77+ out = append (out , "--namespace=" + config .Namespace )
78+ if config .ClientCertPath != "" {
79+ clientCertPath , err := filepath .Abs (config .ClientCertPath )
80+ if err != nil {
81+ return nil , err
82+ }
83+ out = append (out , "--client-cert-path=" + clientCertPath )
84+ }
85+ if config .ClientKeyPath != "" {
86+ clientKeyPath , err := filepath .Abs (config .ClientKeyPath )
87+ if err != nil {
88+ return nil , err
89+ }
90+ out = append (out , "--client-key-path=" + clientKeyPath )
91+ }
92+ if config .SummaryURI != "" {
93+ out = append (out , "--summary-uri=" + config .SummaryURI )
94+ }
95+ if config .HTTPProxyURL != "" {
96+ out = append (out , "--http-proxy-url" , config .HTTPProxyURL )
97+ }
98+ if config .ProxyControlURI != "" {
99+ out = append (out , "--proxy-control-uri=" + config .ProxyControlURI )
100+ }
101+ if config .ProxyListenHostPort != "" {
102+ out = append (out , "--proxy-listen-host-port=" + config .ProxyListenHostPort )
103+ }
104+ return out , nil
69105}
70106
71107// dockerRunFlags are a subset of flags that apply when running in a docker container
@@ -134,6 +170,7 @@ type Runner struct {
134170 rootDir string
135171 createTime time.Time
136172 program sdkbuild.Program
173+ proxy * exec.Cmd
137174}
138175
139176// NewRunner creates a new runner for the given config.
@@ -188,13 +225,17 @@ func (r *Runner) Run(ctx context.Context, patterns []string) error {
188225 }
189226 // Aa task queue to every feature
190227 run := & cmd.Run {Features : make ([]cmd.RunFeature , len (features ))}
191- var expectsProxy bool
228+ var expectsHTTPProxy bool
229+ var expectsGrpcProxy bool
192230 for i , feature := range features {
193231 run .Features [i ].Dir = feature .Dir
194232 run .Features [i ].TaskQueue = fmt .Sprintf ("features-%v-%v" , feature .Dir , uuid .NewString ())
195233 run .Features [i ].Config = feature .Config
196234 if feature .Config .ExpectUnauthedProxyCount > 0 || feature .Config .ExpectAuthedProxyCount > 0 {
197- expectsProxy = true
235+ expectsHTTPProxy = true
236+ }
237+ if feature .Config .GrpcProxy {
238+ expectsGrpcProxy = true
198239 }
199240 }
200241
@@ -228,15 +269,32 @@ func (r *Runner) Run(ctx context.Context, patterns []string) error {
228269 }
229270
230271 // If any feature requires an HTTP proxy, we must run it
231- var proxyServer * harness.HTTPConnectProxyServer
232- if expectsProxy {
233- proxyServer , err = harness .StartHTTPConnectProxyServer (harness.HTTPConnectProxyServerOptions {Log : r .log })
272+ var httpProxyServer * harness.HTTPConnectProxyServer
273+ if expectsHTTPProxy {
274+ httpProxyServer , err = harness .StartHTTPConnectProxyServer (harness.HTTPConnectProxyServerOptions {Log : r .log })
275+ if err != nil {
276+ return fmt .Errorf ("could not start http proxy server: %w" , err )
277+ }
278+ r .config .HTTPProxyURL = "https://" + httpProxyServer .Address
279+ r .log .Info ("Started HTTP CONNECT proxy server" , "address" , httpProxyServer .Address )
280+ defer httpProxyServer .Close ()
281+ }
282+
283+ // if any feature requires a gRPC proxy, we must run it
284+ if expectsGrpcProxy {
285+ grpcProxyServer , err := harness .StartGRPCProxyServer (harness.GRPCProxyServerOptions {
286+ DialAddress : r .config .Server ,
287+ ClientCertPath : r .config .ClientCertPath ,
288+ ClientKeyPath : r .config .ClientKeyPath ,
289+ Log : r .log ,
290+ })
234291 if err != nil {
235- return fmt .Errorf ("could not start proxy server: %w" , err )
292+ return fmt .Errorf ("could not start grpc proxy server: %w" , err )
236293 }
237- r .config .HTTPProxyURL = "https://" + proxyServer .Address
238- r .log .Info ("Started HTTP CONNECT proxy server" , "address" , proxyServer .Address )
239- defer proxyServer .Close ()
294+ r .config .ProxyListenHostPort = grpcProxyServer .ProxyAddress ()
295+ r .config .ProxyControlURI = "http://" + grpcProxyServer .ControlAddress ()
296+ r .log .Info ("Started gRPC proxy server" , "address" , grpcProxyServer .ProxyAddress (), "control" , grpcProxyServer .ControlAddress ())
297+ defer grpcProxyServer .Close ()
240298 }
241299
242300 // Ensure any created temp dir is cleaned on ctrl-c or normal exit
@@ -251,14 +309,14 @@ func (r *Runner) Run(ctx context.Context, patterns []string) error {
251309 defer r .destroyTempDir ()
252310 }
253311
254- l , err := net .Listen ("tcp" , summaryListenAddr )
312+ summaryListener , err := net .Listen ("tcp" , freePortListenAddr )
255313 if err != nil {
256314 return err
257315 }
258- defer l .Close ()
316+ defer summaryListener .Close ()
259317 summaryChan := make (chan Summary )
260- go r .summaryServer (l , summaryChan )
261- r .config .SummaryURI = "tcp://" + l .Addr ().String ()
318+ go r .summaryServer (summaryListener , summaryChan )
319+ r .config .SummaryURI = "tcp://" + summaryListener .Addr ().String ()
262320
263321 err = nil
264322 switch r .config .Lang {
@@ -273,12 +331,14 @@ func (r *Runner) Run(ctx context.Context, patterns []string) error {
273331 }
274332 } else {
275333 err = cmd .NewRunner (cmd.RunConfig {
276- Server : r .config .Server ,
277- Namespace : r .config .Namespace ,
278- ClientCertPath : r .config .ClientCertPath ,
279- ClientKeyPath : r .config .ClientKeyPath ,
280- SummaryURI : r .config .SummaryURI ,
281- HTTPProxyURL : r .config .HTTPProxyURL ,
334+ Server : r .config .Server ,
335+ Namespace : r .config .Namespace ,
336+ ClientCertPath : r .config .ClientCertPath ,
337+ ClientKeyPath : r .config .ClientKeyPath ,
338+ SummaryURI : r .config .SummaryURI ,
339+ HTTPProxyURL : r .config .HTTPProxyURL ,
340+ ProxyControlURI : r .config .ProxyControlURI ,
341+ ProxyListenHostPort : r .config .ProxyListenHostPort ,
282342 }).Run (ctx , run )
283343 }
284344 case "java" :
@@ -315,7 +375,7 @@ func (r *Runner) Run(ctx context.Context, patterns []string) error {
315375 if err != nil {
316376 return err
317377 }
318- l .Close ()
378+ summaryListener .Close ()
319379 summary , ok := <- summaryChan
320380 if ! ok {
321381 r .log .Debug ("did not receive a test run summary - adopting legacy behavior of assuming no tests were skipped" )
@@ -327,7 +387,7 @@ func (r *Runner) Run(ctx context.Context, patterns []string) error {
327387 // For features that expected proxy connections, count how many expected
328388 // ignoring skips and compare count with actual. If any failed we don't need
329389 // even do the comparison.
330- if proxyServer != nil {
390+ if httpProxyServer != nil {
331391 var anyFailed bool
332392 var expectUnauthedProxyCount , expectAuthedProxyCount int
333393 for _ , summ := range summary {
@@ -345,21 +405,26 @@ func (r *Runner) Run(ctx context.Context, patterns []string) error {
345405 }
346406 }
347407 if ! anyFailed {
348- if proxyServer .UnauthedConnectionsTunneled .Load () != uint32 (expectUnauthedProxyCount ) {
408+ if httpProxyServer .UnauthedConnectionsTunneled .Load () != uint32 (expectUnauthedProxyCount ) {
349409 return fmt .Errorf ("expected %v unauthed HTTP proxy connections, got %v" ,
350- expectUnauthedProxyCount , proxyServer .UnauthedConnectionsTunneled .Load ())
351- } else if proxyServer .AuthedConnectionsTunneled .Load () != uint32 (expectAuthedProxyCount ) {
410+ expectUnauthedProxyCount , httpProxyServer .UnauthedConnectionsTunneled .Load ())
411+ } else if httpProxyServer .AuthedConnectionsTunneled .Load () != uint32 (expectAuthedProxyCount ) {
352412 return fmt .Errorf ("expected %v authed HTTP proxy connections, got %v" ,
353- expectAuthedProxyCount , proxyServer .AuthedConnectionsTunneled .Load ())
413+ expectAuthedProxyCount , httpProxyServer .AuthedConnectionsTunneled .Load ())
354414 } else {
355415 r .log .Debug ("Matched expected HTTP proxy connections" ,
356- "expectUnauthed" , expectUnauthedProxyCount , "actualUnauthed" , proxyServer .UnauthedConnectionsTunneled .Load (),
357- "expectAuthed" , expectAuthedProxyCount , "actualAuthed" , proxyServer .AuthedConnectionsTunneled .Load ())
416+ "expectUnauthed" , expectUnauthedProxyCount , "actualUnauthed" , httpProxyServer .UnauthedConnectionsTunneled .Load (),
417+ "expectAuthed" , expectAuthedProxyCount , "actualAuthed" , httpProxyServer .AuthedConnectionsTunneled .Load ())
358418 }
359419 }
360420 }
361421
362- return r .handleHistory (ctx , run , summary )
422+ err = r .handleHistory (ctx , run , summary )
423+ if err != nil {
424+ return err
425+ }
426+
427+ return nil
363428}
364429
365430func (r * Runner ) handleHistory (ctx context.Context , run * cmd.Run , summary Summary ) error {
0 commit comments