1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package integration
16
17 import (
18 "context"
19 "fmt"
20 "net"
21 "net/http"
22 "sync"
23 "time"
24
25 "github.com/google/certificate-transparency-go/trillian/ctfe"
26 "github.com/google/certificate-transparency-go/trillian/ctfe/configpb"
27 "github.com/google/trillian"
28 "github.com/google/trillian/client"
29 "github.com/google/trillian/monitoring/prometheus"
30 "github.com/google/trillian/testonly/integration"
31 "github.com/prometheus/client_golang/prometheus/promhttp"
32 "k8s.io/klog/v2"
33
34 stestonly "github.com/google/trillian/storage/testonly"
35 )
36
37
38
39 type CTLogEnv struct {
40 logEnv *integration.LogEnv
41 wg *sync.WaitGroup
42 ctListener net.Listener
43 ctHTTPServer *http.Server
44 CTAddr string
45 }
46
47
48
49
50 func NewCTLogEnv(ctx context.Context, cfgs []*configpb.LogConfig, numSequencers int, testID string) (*CTLogEnv, error) {
51
52 logEnv, err := integration.NewLogEnvWithGRPCOptions(ctx, numSequencers, nil, nil)
53 if err != nil {
54 return nil, fmt.Errorf("failed to create LogEnv: %v", err)
55 }
56
57
58 for _, cfg := range cfgs {
59 tree, err := client.CreateAndInitTree(ctx,
60 &trillian.CreateTreeRequest{Tree: stestonly.LogTree},
61 logEnv.Admin, logEnv.Log)
62 if err != nil {
63 return nil, fmt.Errorf("failed to provision log %d: %v", cfg.LogId, err)
64 }
65
66 cfg.LogId = tree.TreeId
67 }
68
69
70 addr, listener, err := listen()
71 if err != nil {
72 return nil, fmt.Errorf("failed to find an unused port for CT personality: %v", err)
73 }
74 server := http.Server{Addr: addr, Handler: nil}
75 var wg sync.WaitGroup
76 wg.Add(1)
77 go func(env *integration.LogEnv, server *http.Server, listener net.Listener, cfgs []*configpb.LogConfig) {
78 defer wg.Done()
79 cl := trillian.NewTrillianLogClient(env.ClientConn)
80 for _, cfg := range cfgs {
81 vCfg, err := ctfe.ValidateLogConfig(cfg)
82 if err != nil {
83 klog.Fatalf("ValidateLogConfig failed: %+v: %v", cfg, err)
84 }
85 opts := ctfe.InstanceOptions{
86 Validated: vCfg,
87 Client: cl,
88 Deadline: 10 * time.Second,
89 MetricFactory: prometheus.MetricFactory{},
90 RequestLog: new(ctfe.DefaultRequestLog),
91 }
92 inst, err := ctfe.SetUpInstance(ctx, opts)
93 if err != nil {
94 klog.Fatalf("Failed to set up log instance for %+v: %v", cfg, err)
95 }
96 for path, handler := range inst.Handlers {
97 http.Handle(path, handler)
98 }
99 }
100 http.Handle("/metrics", promhttp.Handler())
101 if err := server.Serve(listener); err != http.ErrServerClosed {
102 klog.Fatalf("server.Serve(): %v", err)
103 }
104 }(logEnv, &server, listener, cfgs)
105 return &CTLogEnv{
106 logEnv: logEnv,
107 wg: &wg,
108 ctListener: listener,
109 ctHTTPServer: &server,
110 CTAddr: addr,
111 }, nil
112 }
113
114
115 func (env *CTLogEnv) Close() {
116 env.ctListener.Close()
117 env.wg.Wait()
118 env.logEnv.Close()
119 }
120
121
122 func listen() (string, net.Listener, error) {
123 lis, err := net.Listen("tcp", ":0")
124 if err != nil {
125 return "", nil, err
126 }
127 _, port, err := net.SplitHostPort(lis.Addr().String())
128 if err != nil {
129 return "", nil, err
130 }
131 addr := "localhost:" + port
132 return addr, lis, nil
133 }
134
View as plain text