xds/bootstrap: Add support for `grpc_server_resource_name_id`. (#4030)
diff --git a/xds/internal/client/bootstrap/bootstrap.go b/xds/internal/client/bootstrap/bootstrap.go
index ca7c96c..87abecd 100644
--- a/xds/internal/client/bootstrap/bootstrap.go
+++ b/xds/internal/client/bootstrap/bootstrap.go
@@ -78,6 +78,10 @@
// CertProviderConfigs contains a mapping from certificate provider plugin
// instance names to parsed buildable configs.
CertProviderConfigs map[string]*certprovider.BuildableConfig
+ // ServerResourceNameID contains the value to be used as the id in the
+ // resource name used to fetch the Listener resource on the xDS-enabled gRPC
+ // server.
+ ServerResourceNameID string
}
type channelCreds struct {
@@ -103,19 +107,20 @@
// "config": <JSON object containing config for the type>
// }
// ],
-// "server_features": [ ... ]
-// "certificate_providers" : {
-// "default": {
-// "plugin_name": "default-plugin-name",
-// "config": { default plugin config in JSON }
-// },
-// "foo": {
-// "plugin_name": "foo",
-// "config": { foo plugin config in JSON }
-// }
-// }
// },
-// "node": <JSON form of Node proto>
+// "node": <JSON form of Node proto>,
+// "server_features": [ ... ],
+// "certificate_providers" : {
+// "default": {
+// "plugin_name": "default-plugin-name",
+// "config": { default plugin config in JSON }
+// },
+// "foo": {
+// "plugin_name": "foo",
+// "config": { foo plugin config in JSON }
+// }
+// },
+// "grpc_server_resource_name_id": "grpc/server"
// }
//
// Currently, we support exactly one type of credential, which is
@@ -222,6 +227,10 @@
configs[instance] = bc
}
config.CertProviderConfigs = configs
+ case "grpc_server_resource_name_id":
+ if err := json.Unmarshal(v, &config.ServerResourceNameID); err != nil {
+ return nil, fmt.Errorf("xds: json.Unmarshal(%v) for field %q failed during bootstrap: %v", string(v), k, err)
+ }
}
// Do not fail the xDS bootstrap when an unknown field is seen. This can
// happen when an older version client reads a newer version bootstrap
diff --git a/xds/internal/client/bootstrap/bootstrap_test.go b/xds/internal/client/bootstrap/bootstrap_test.go
index 1b9deca..6691ff4 100644
--- a/xds/internal/client/bootstrap/bootstrap_test.go
+++ b/xds/internal/client/bootstrap/bootstrap_test.go
@@ -239,6 +239,9 @@
if diff := cmp.Diff(want.NodeProto, c.NodeProto, cmp.Comparer(proto.Equal)); diff != "" {
return fmt.Errorf("config.NodeProto diff (-want, +got):\n%s", diff)
}
+ if c.ServerResourceNameID != want.ServerResourceNameID {
+ return fmt.Errorf("config.ServerResourceNameID is %q, want %q", c.ServerResourceNameID, want.ServerResourceNameID)
+ }
// A vanilla cmp.Equal or cmp.Diff will not produce useful error message
// here. So, we iterate through the list of configs and compare them one at
@@ -699,3 +702,81 @@
})
}
}
+
+func TestNewConfigWithServerResourceNameID(t *testing.T) {
+ cancel := setupBootstrapOverride(map[string]string{
+ "badServerResourceNameID": `
+ {
+ "node": {
+ "id": "ENVOY_NODE_ID",
+ "metadata": {
+ "TRAFFICDIRECTOR_GRPC_HOSTNAME": "trafficdirector"
+ }
+ },
+ "xds_servers" : [{
+ "server_uri": "trafficdirector.googleapis.com:443",
+ "channel_creds": [
+ { "type": "google_default" }
+ ]
+ }],
+ "grpc_server_resource_name_id": 123456789
+ }`,
+ "goodServerResourceNameID": `
+ {
+ "node": {
+ "id": "ENVOY_NODE_ID",
+ "metadata": {
+ "TRAFFICDIRECTOR_GRPC_HOSTNAME": "trafficdirector"
+ }
+ },
+ "xds_servers" : [{
+ "server_uri": "trafficdirector.googleapis.com:443",
+ "channel_creds": [
+ { "type": "google_default" }
+ ]
+ }],
+ "grpc_server_resource_name_id": "grpc/server"
+ }`,
+ })
+ defer cancel()
+
+ tests := []struct {
+ name string
+ wantConfig *Config
+ wantErr bool
+ }{
+ {
+ name: "badServerResourceNameID",
+ wantErr: true,
+ },
+ {
+ name: "goodServerResourceNameID",
+ wantConfig: &Config{
+ BalancerName: "trafficdirector.googleapis.com:443",
+ Creds: grpc.WithCredentialsBundle(google.NewComputeEngineCredentials()),
+ TransportAPI: version.TransportV2,
+ NodeProto: v2NodeProto,
+ ServerResourceNameID: "grpc/server",
+ },
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ origBootstrapFileName := env.BootstrapFileName
+ env.BootstrapFileName = test.name
+ defer func() { env.BootstrapFileName = origBootstrapFileName }()
+
+ c, err := NewConfig()
+ if (err != nil) != test.wantErr {
+ t.Fatalf("NewConfig() returned (%+v, %v), wantErr: %v", c, err, test.wantErr)
+ }
+ if test.wantErr {
+ return
+ }
+ if err := c.compare(test.wantConfig); err != nil {
+ t.Fatal(err)
+ }
+ })
+ }
+}