Skip to content

Commit aff517b

Browse files
authored
xds: make e2e tests use a single management server instance (#4399)
1 parent 0439465 commit aff517b

File tree

5 files changed

+203
-206
lines changed

5 files changed

+203
-206
lines changed

xds/internal/test/xds_client_integration_test.go

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,48 +23,26 @@ package xds_test
2323

2424
import (
2525
"context"
26+
"fmt"
2627
"net"
2728
"testing"
2829

29-
"github.com/google/uuid"
3030
"google.golang.org/grpc"
3131
"google.golang.org/grpc/credentials/insecure"
32-
"google.golang.org/grpc/internal/xds"
3332
"google.golang.org/grpc/xds/internal/testutils"
3433
"google.golang.org/grpc/xds/internal/testutils/e2e"
3534

3635
testpb "google.golang.org/grpc/test/grpc_testing"
3736
)
3837

3938
// clientSetup performs a bunch of steps common to all xDS client tests here:
40-
// - spin up an xDS management server on a local port
4139
// - spin up a gRPC server and register the test service on it
4240
// - create a local TCP listener and start serving on it
4341
//
4442
// Returns the following:
45-
// - the management server: tests use this to configure resources
46-
// - nodeID expected by the management server: this is set in the Node proto
47-
// sent by the xdsClient for queries.
4843
// - the port the server is listening on
4944
// - cleanup function to be invoked by the tests when done
50-
func clientSetup(t *testing.T) (*e2e.ManagementServer, string, uint32, func()) {
51-
// Spin up a xDS management server on a local port.
52-
nodeID := uuid.New().String()
53-
fs, err := e2e.StartManagementServer()
54-
if err != nil {
55-
t.Fatal(err)
56-
}
57-
58-
// Create a bootstrap file in a temporary directory.
59-
bootstrapCleanup, err := xds.SetupBootstrapFile(xds.BootstrapOptions{
60-
Version: xds.TransportV3,
61-
NodeID: nodeID,
62-
ServerURI: fs.Address,
63-
})
64-
if err != nil {
65-
t.Fatal(err)
66-
}
67-
45+
func clientSetup(t *testing.T) (uint32, func()) {
6846
// Initialize a gRPC server and register the stubServer on it.
6947
server := grpc.NewServer()
7048
testpb.RegisterTestServiceServer(server, &testService{})
@@ -81,30 +59,29 @@ func clientSetup(t *testing.T) (*e2e.ManagementServer, string, uint32, func()) {
8159
}
8260
}()
8361

84-
return fs, nodeID, uint32(lis.Addr().(*net.TCPAddr).Port), func() {
85-
fs.Stop()
86-
bootstrapCleanup()
62+
return uint32(lis.Addr().(*net.TCPAddr).Port), func() {
8763
server.Stop()
8864
}
8965
}
9066

9167
func (s) TestClientSideXDS(t *testing.T) {
92-
fs, nodeID, port, cleanup := clientSetup(t)
68+
port, cleanup := clientSetup(t)
9369
defer cleanup()
9470

71+
serviceName := xdsServiceName + "-client-side-xds"
9572
resources := e2e.DefaultClientResources(e2e.ResourceParams{
96-
DialTarget: "myservice",
97-
NodeID: nodeID,
73+
DialTarget: serviceName,
74+
NodeID: xdsClientNodeID,
9875
Host: "localhost",
9976
Port: port,
10077
SecLevel: e2e.SecurityLevelNone,
10178
})
102-
if err := fs.Update(resources); err != nil {
79+
if err := managementServer.Update(resources); err != nil {
10380
t.Fatal(err)
10481
}
10582

10683
// Create a ClientConn and make a successful RPC.
107-
cc, err := grpc.Dial("xds:///myservice", grpc.WithTransportCredentials(insecure.NewCredentials()))
84+
cc, err := grpc.Dial(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()))
10885
if err != nil {
10986
t.Fatalf("failed to dial local test server: %v", err)
11087
}

xds/internal/test/xds_integration_test.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,26 @@ package xds_test
2424

2525
import (
2626
"context"
27+
"crypto/tls"
28+
"crypto/x509"
29+
"encoding/json"
30+
"fmt"
31+
"io/ioutil"
32+
"log"
33+
"os"
34+
"path"
2735
"testing"
2836
"time"
2937

38+
"github.com/google/uuid"
39+
"google.golang.org/grpc/credentials"
3040
"google.golang.org/grpc/internal/grpctest"
41+
"google.golang.org/grpc/internal/leakcheck"
42+
"google.golang.org/grpc/internal/xds/env"
43+
"google.golang.org/grpc/testdata"
44+
"google.golang.org/grpc/xds/internal/testutils/e2e"
45+
46+
xdsinternal "google.golang.org/grpc/internal/xds"
3147
testpb "google.golang.org/grpc/test/grpc_testing"
3248
)
3349

@@ -51,3 +67,148 @@ type testService struct {
5167
func (*testService) EmptyCall(context.Context, *testpb.Empty) (*testpb.Empty, error) {
5268
return &testpb.Empty{}, nil
5369
}
70+
71+
var (
72+
// Globals corresponding to the single instance of the xDS management server
73+
// which is spawned for all the tests in this package.
74+
managementServer *e2e.ManagementServer
75+
xdsClientNodeID string
76+
)
77+
78+
// TestMain sets up an xDS management server, runs all tests, and stops the
79+
// management server.
80+
func TestMain(m *testing.M) {
81+
// The management server is started and stopped from here, but the leakcheck
82+
// runs after every individual test. So, we need to skip the goroutine which
83+
// spawns the management server and is blocked on the call to `Serve()`.
84+
leakcheck.RegisterIgnoreGoroutine("e2e.StartManagementServer")
85+
86+
cancel, err := setupManagementServer()
87+
if err != nil {
88+
log.Printf("setupManagementServer() failed: %v", err)
89+
os.Exit(1)
90+
}
91+
92+
code := m.Run()
93+
cancel()
94+
os.Exit(code)
95+
}
96+
97+
func createTmpFile(src, dst string) error {
98+
data, err := ioutil.ReadFile(src)
99+
if err != nil {
100+
return fmt.Errorf("ioutil.ReadFile(%q) failed: %v", src, err)
101+
}
102+
if err := ioutil.WriteFile(dst, data, os.ModePerm); err != nil {
103+
return fmt.Errorf("ioutil.WriteFile(%q) failed: %v", dst, err)
104+
}
105+
return nil
106+
}
107+
108+
// createTempDirWithFiles creates a temporary directory under the system default
109+
// tempDir with the given dirSuffix. It also reads from certSrc, keySrc and
110+
// rootSrc files are creates appropriate files under the newly create tempDir.
111+
// Returns the name of the created tempDir.
112+
func createTmpDirWithFiles(dirSuffix, certSrc, keySrc, rootSrc string) (string, error) {
113+
// Create a temp directory. Passing an empty string for the first argument
114+
// uses the system temp directory.
115+
dir, err := ioutil.TempDir("", dirSuffix)
116+
if err != nil {
117+
return "", fmt.Errorf("ioutil.TempDir() failed: %v", err)
118+
}
119+
120+
if err := createTmpFile(testdata.Path(certSrc), path.Join(dir, certFile)); err != nil {
121+
return "", err
122+
}
123+
if err := createTmpFile(testdata.Path(keySrc), path.Join(dir, keyFile)); err != nil {
124+
return "", err
125+
}
126+
if err := createTmpFile(testdata.Path(rootSrc), path.Join(dir, rootFile)); err != nil {
127+
return "", err
128+
}
129+
return dir, nil
130+
}
131+
132+
// createClientTLSCredentials creates client-side TLS transport credentials.
133+
func createClientTLSCredentials(t *testing.T) credentials.TransportCredentials {
134+
t.Helper()
135+
136+
cert, err := tls.LoadX509KeyPair(testdata.Path("x509/client1_cert.pem"), testdata.Path("x509/client1_key.pem"))
137+
if err != nil {
138+
t.Fatalf("tls.LoadX509KeyPair(x509/client1_cert.pem, x509/client1_key.pem) failed: %v", err)
139+
}
140+
b, err := ioutil.ReadFile(testdata.Path("x509/server_ca_cert.pem"))
141+
if err != nil {
142+
t.Fatalf("ioutil.ReadFile(x509/server_ca_cert.pem) failed: %v", err)
143+
}
144+
roots := x509.NewCertPool()
145+
if !roots.AppendCertsFromPEM(b) {
146+
t.Fatal("failed to append certificates")
147+
}
148+
return credentials.NewTLS(&tls.Config{
149+
Certificates: []tls.Certificate{cert},
150+
RootCAs: roots,
151+
ServerName: "x.test.example.com",
152+
})
153+
}
154+
155+
// setupManagement server performs the following:
156+
// - spin up an xDS management server on a local port
157+
// - set up certificates for consumption by the file_watcher plugin
158+
// - sets up the global variables which refer to this management server and the
159+
// nodeID to be used when talking to this management server.
160+
//
161+
// Returns a function to be invoked by the caller to stop the management server.
162+
func setupManagementServer() (func(), error) {
163+
// Turn on the env var protection for client-side security.
164+
origClientSideSecurityEnvVar := env.ClientSideSecuritySupport
165+
env.ClientSideSecuritySupport = true
166+
167+
// Spin up an xDS management server on a local port.
168+
var err error
169+
managementServer, err = e2e.StartManagementServer()
170+
if err != nil {
171+
return nil, err
172+
}
173+
174+
// Create a directory to hold certs and key files used on the server side.
175+
serverDir, err := createTmpDirWithFiles("testServerSideXDS*", "x509/server1_cert.pem", "x509/server1_key.pem", "x509/client_ca_cert.pem")
176+
if err != nil {
177+
managementServer.Stop()
178+
return nil, err
179+
}
180+
181+
// Create a directory to hold certs and key files used on the client side.
182+
clientDir, err := createTmpDirWithFiles("testClientSideXDS*", "x509/client1_cert.pem", "x509/client1_key.pem", "x509/server_ca_cert.pem")
183+
if err != nil {
184+
managementServer.Stop()
185+
return nil, err
186+
}
187+
188+
// Create certificate providers section of the bootstrap config with entries
189+
// for both the client and server sides.
190+
cpc := map[string]json.RawMessage{
191+
e2e.ServerSideCertProviderInstance: e2e.DefaultFileWatcherConfig(path.Join(serverDir, certFile), path.Join(serverDir, keyFile), path.Join(serverDir, rootFile)),
192+
e2e.ClientSideCertProviderInstance: e2e.DefaultFileWatcherConfig(path.Join(clientDir, certFile), path.Join(clientDir, keyFile), path.Join(clientDir, rootFile)),
193+
}
194+
195+
// Create a bootstrap file in a temporary directory.
196+
xdsClientNodeID = uuid.New().String()
197+
bootstrapCleanup, err := xdsinternal.SetupBootstrapFile(xdsinternal.BootstrapOptions{
198+
Version: xdsinternal.TransportV3,
199+
NodeID: xdsClientNodeID,
200+
ServerURI: managementServer.Address,
201+
CertificateProviders: cpc,
202+
ServerListenerResourceNameTemplate: e2e.ServerListenerResourceNameTemplate,
203+
})
204+
if err != nil {
205+
managementServer.Stop()
206+
return nil, err
207+
}
208+
209+
return func() {
210+
managementServer.Stop()
211+
bootstrapCleanup()
212+
env.ClientSideSecuritySupport = origClientSideSecurityEnvVar
213+
}, nil
214+
}

0 commit comments

Comments
 (0)