Skip to content

Commit 3f84a73

Browse files
authored
Merge pull request #2821 from murgatroid99/grpc-js_subchannel_credentials_override
grpc-js: Construct LB policies with credentials and enable them to override subchannel credentials
2 parents e0ab3c3 + 57f0a71 commit 3f84a73

18 files changed

+88
-60
lines changed

Diff for: packages/grpc-js-xds/interop/xds-interop-client.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const RPC_BEHAVIOR_CHILD_CONFIG = parseLoadBalancingConfig({round_robin: {}});
8888
class RpcBehaviorLoadBalancer implements LoadBalancer {
8989
private child: ChildLoadBalancerHandler;
9090
private latestConfig: RpcBehaviorLoadBalancingConfig | null = null;
91-
constructor(channelControlHelper: ChannelControlHelper, options: grpc.ChannelOptions) {
91+
constructor(channelControlHelper: ChannelControlHelper, credentials: grpc.ChannelCredentials, options: grpc.ChannelOptions) {
9292
const childChannelControlHelper = createChildChannelControlHelper(channelControlHelper, {
9393
updateState: (connectivityState, picker) => {
9494
if (connectivityState === grpc.connectivityState.READY && this.latestConfig) {
@@ -97,7 +97,7 @@ class RpcBehaviorLoadBalancer implements LoadBalancer {
9797
channelControlHelper.updateState(connectivityState, picker);
9898
}
9999
});
100-
this.child = new ChildLoadBalancerHandler(childChannelControlHelper, options);
100+
this.child = new ChildLoadBalancerHandler(childChannelControlHelper, credentials, options);
101101
}
102102
updateAddressList(endpointList: Endpoint[], lbConfig: TypedLoadBalancingConfig, attributes: { [key: string]: unknown; }): void {
103103
if (!(lbConfig instanceof RpcBehaviorLoadBalancingConfig)) {

Diff for: packages/grpc-js-xds/src/load-balancer-cds.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
import { connectivityState, status, Metadata, logVerbosity, experimental, LoadBalancingConfig, ChannelOptions } from '@grpc/grpc-js';
18+
import { connectivityState, status, Metadata, logVerbosity, experimental, LoadBalancingConfig, ChannelOptions, ChannelCredentials } from '@grpc/grpc-js';
1919
import { getSingletonXdsClient, Watcher, XdsClient } from './xds-client';
2020
import { Cluster__Output } from './generated/envoy/config/cluster/v3/Cluster';
2121
import Endpoint = experimental.Endpoint;
@@ -155,8 +155,8 @@ export class CdsLoadBalancer implements LoadBalancer {
155155

156156
private updatedChild = false;
157157

158-
constructor(private readonly channelControlHelper: ChannelControlHelper, options: ChannelOptions) {
159-
this.childBalancer = new XdsClusterResolverChildPolicyHandler(channelControlHelper, options);
158+
constructor(private readonly channelControlHelper: ChannelControlHelper, credentials: ChannelCredentials, options: ChannelOptions) {
159+
this.childBalancer = new XdsClusterResolverChildPolicyHandler(channelControlHelper, credentials, options);
160160
}
161161

162162
private reportError(errorMessage: string) {

Diff for: packages/grpc-js-xds/src/load-balancer-priority.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
import { connectivityState as ConnectivityState, status as Status, Metadata, logVerbosity as LogVerbosity, experimental, LoadBalancingConfig, ChannelOptions } from '@grpc/grpc-js';
18+
import { connectivityState as ConnectivityState, status as Status, Metadata, logVerbosity as LogVerbosity, experimental, LoadBalancingConfig, ChannelOptions, ChannelCredentials } from '@grpc/grpc-js';
1919
import LoadBalancer = experimental.LoadBalancer;
2020
import ChannelControlHelper = experimental.ChannelControlHelper;
2121
import registerLoadBalancerType = experimental.registerLoadBalancerType;
@@ -197,7 +197,7 @@ export class PriorityLoadBalancer implements LoadBalancer {
197197
this.parent.channelControlHelper.requestReresolution();
198198
}
199199
}
200-
}), parent.options);
200+
}), parent.credentials, parent.options);
201201
this.picker = new QueuePicker(this.childBalancer);
202202
this.startFailoverTimer();
203203
}
@@ -323,7 +323,7 @@ export class PriorityLoadBalancer implements LoadBalancer {
323323

324324
private updatesPaused = false;
325325

326-
constructor(private channelControlHelper: ChannelControlHelper, private options: ChannelOptions) {}
326+
constructor(private channelControlHelper: ChannelControlHelper, private credentials: ChannelCredentials, private options: ChannelOptions) {}
327327

328328
private updateState(state: ConnectivityState, picker: Picker) {
329329
trace(

Diff for: packages/grpc-js-xds/src/load-balancer-ring-hash.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
import { experimental, logVerbosity, connectivityState, status, Metadata, ChannelOptions, LoadBalancingConfig } from '@grpc/grpc-js';
18+
import { experimental, logVerbosity, connectivityState, status, Metadata, ChannelOptions, LoadBalancingConfig, ChannelCredentials } from '@grpc/grpc-js';
1919
import { isLocalityEndpoint } from './load-balancer-priority';
2020
import TypedLoadBalancingConfig = experimental.TypedLoadBalancingConfig;
2121
import LeafLoadBalancer = experimental.LeafLoadBalancer;
@@ -226,7 +226,7 @@ class RingHashLoadBalancer implements LoadBalancer {
226226
private currentState: connectivityState = connectivityState.IDLE;
227227
private ring: RingEntry[] = [];
228228
private ringHashSizeCap = DEFAULT_RING_SIZE_CAP;
229-
constructor(private channelControlHelper: ChannelControlHelper, private options: ChannelOptions) {
229+
constructor(private channelControlHelper: ChannelControlHelper, private credentials: ChannelCredentials, private options: ChannelOptions) {
230230
this.childChannelControlHelper = createChildChannelControlHelper(
231231
channelControlHelper,
232232
{
@@ -407,7 +407,7 @@ class RingHashLoadBalancer implements LoadBalancer {
407407
} else {
408408
this.leafMap.set(
409409
endpoint,
410-
new LeafLoadBalancer(endpoint, this.childChannelControlHelper, this.options)
410+
new LeafLoadBalancer(endpoint, this.childChannelControlHelper, this.credentials, this.options)
411411
);
412412
}
413413
const weight = this.leafWeightMap.get(endpoint);

Diff for: packages/grpc-js-xds/src/load-balancer-weighted-target.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
import { connectivityState as ConnectivityState, status as Status, Metadata, logVerbosity, experimental, LoadBalancingConfig, ChannelOptions } from "@grpc/grpc-js";
18+
import { connectivityState as ConnectivityState, status as Status, Metadata, logVerbosity, experimental, LoadBalancingConfig, ChannelOptions, ChannelCredentials } from "@grpc/grpc-js";
1919
import { isLocalityEndpoint, LocalityEndpoint } from "./load-balancer-priority";
2020
import TypedLoadBalancingConfig = experimental.TypedLoadBalancingConfig;
2121
import LoadBalancer = experimental.LoadBalancer;
@@ -178,7 +178,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer {
178178
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
179179
this.updateState(connectivityState, picker);
180180
},
181-
}), parent.options);
181+
}), parent.credentials, parent.options);
182182

183183
this.picker = new QueuePicker(this.childBalancer);
184184
}
@@ -243,7 +243,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer {
243243
private targetList: string[] = [];
244244
private updatesPaused = false;
245245

246-
constructor(private channelControlHelper: ChannelControlHelper, private options: ChannelOptions) {}
246+
constructor(private channelControlHelper: ChannelControlHelper, private credentials: ChannelCredentials, private options: ChannelOptions) {}
247247

248248
private maybeUpdateState() {
249249
if (!this.updatesPaused) {

Diff for: packages/grpc-js-xds/src/load-balancer-xds-cluster-impl.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
import { experimental, logVerbosity, status as Status, Metadata, connectivityState, ChannelOptions } from "@grpc/grpc-js";
18+
import { experimental, logVerbosity, status as Status, Metadata, connectivityState, ChannelOptions, ChannelCredentials } from "@grpc/grpc-js";
1919
import { validateXdsServerConfig, XdsServerConfig } from "./xds-bootstrap";
2020
import { getSingletonXdsClient, XdsClient, XdsClusterDropStats, XdsClusterLocalityStats } from "./xds-client";
2121
import { LocalityEndpoint } from "./load-balancer-priority";
@@ -253,13 +253,13 @@ class XdsClusterImplBalancer implements LoadBalancer {
253253
private clusterDropStats: XdsClusterDropStats | null = null;
254254
private xdsClient: XdsClient | null = null;
255255

256-
constructor(private readonly channelControlHelper: ChannelControlHelper, options: ChannelOptions) {
256+
constructor(private readonly channelControlHelper: ChannelControlHelper, credentials: ChannelCredentials, options: ChannelOptions) {
257257
this.childBalancer = new ChildLoadBalancerHandler(createChildChannelControlHelper(channelControlHelper, {
258-
createSubchannel: (subchannelAddress, subchannelArgs) => {
258+
createSubchannel: (subchannelAddress, subchannelArgs, credentialsOverride) => {
259259
if (!this.xdsClient || !this.latestConfig || !this.lastestEndpointList) {
260260
throw new Error('xds_cluster_impl: invalid state: createSubchannel called with xdsClient or latestConfig not populated');
261261
}
262-
const wrapperChild = channelControlHelper.createSubchannel(subchannelAddress, subchannelArgs);
262+
const wrapperChild = channelControlHelper.createSubchannel(subchannelAddress, subchannelArgs, credentialsOverride);
263263
let locality: Locality__Output | null = null;
264264
for (const endpoint of this.lastestEndpointList) {
265265
if (endpointHasAddress(endpoint, subchannelAddress)) {
@@ -290,7 +290,7 @@ class XdsClusterImplBalancer implements LoadBalancer {
290290
channelControlHelper.updateState(connectivityState, picker);
291291
}
292292
}
293-
}), options);
293+
}), credentials, options);
294294
}
295295
updateAddressList(endpointList: Endpoint[], lbConfig: TypedLoadBalancingConfig, attributes: { [key: string]: unknown; }): void {
296296
if (!(lbConfig instanceof XdsClusterImplLoadBalancingConfig)) {

Diff for: packages/grpc-js-xds/src/load-balancer-xds-cluster-manager.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
import { connectivityState as ConnectivityState, status as Status, experimental, logVerbosity, Metadata, status, ChannelOptions } from "@grpc/grpc-js/";
18+
import { connectivityState as ConnectivityState, status as Status, experimental, logVerbosity, Metadata, status, ChannelOptions, ChannelCredentials } from "@grpc/grpc-js/";
1919

2020
import TypedLoadBalancingConfig = experimental.TypedLoadBalancingConfig;
2121
import LoadBalancer = experimental.LoadBalancer;
@@ -131,7 +131,7 @@ class XdsClusterManager implements LoadBalancer {
131131
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
132132
this.updateState(connectivityState, picker);
133133
},
134-
}), parent.options);
134+
}), parent.credentials, parent.options);
135135

136136
this.picker = new QueuePicker(this.childBalancer);
137137
}
@@ -167,7 +167,7 @@ class XdsClusterManager implements LoadBalancer {
167167
// Shutdown is a placeholder value that will never appear in normal operation.
168168
private currentState: ConnectivityState = ConnectivityState.SHUTDOWN;
169169
private updatesPaused = false;
170-
constructor(private channelControlHelper: ChannelControlHelper, private options: ChannelOptions) {}
170+
constructor(private channelControlHelper: ChannelControlHelper, private credentials: ChannelCredentials, private options: ChannelOptions) {}
171171

172172
private maybeUpdateState() {
173173
if (!this.updatesPaused) {

Diff for: packages/grpc-js-xds/src/load-balancer-xds-cluster-resolver.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
import { ChannelOptions, LoadBalancingConfig, Metadata, connectivityState, experimental, logVerbosity, status } from "@grpc/grpc-js";
18+
import { ChannelCredentials, ChannelOptions, LoadBalancingConfig, Metadata, connectivityState, experimental, logVerbosity, status } from "@grpc/grpc-js";
1919
import { registerLoadBalancerType } from "@grpc/grpc-js/build/src/load-balancer";
2020
import { EXPERIMENTAL_DUALSTACK_ENDPOINTS, EXPERIMENTAL_OUTLIER_DETECTION } from "./environment";
2121
import { Locality__Output } from "./generated/envoy/config/core/v3/Locality";
@@ -249,14 +249,14 @@ export class XdsClusterResolver implements LoadBalancer {
249249
private xdsClient: XdsClient | null = null;
250250
private childBalancer: ChildLoadBalancerHandler;
251251

252-
constructor(private readonly channelControlHelper: ChannelControlHelper, options: ChannelOptions) {
252+
constructor(private readonly channelControlHelper: ChannelControlHelper, credentials: ChannelCredentials, options: ChannelOptions) {
253253
this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(channelControlHelper, {
254254
requestReresolution: () => {
255255
for (const entry of this.discoveryMechanismList) {
256256
entry.resolver?.updateResolution();
257257
}
258258
}
259-
}), options);
259+
}), credentials, options);
260260
}
261261

262262
private maybeUpdateChild() {

Diff for: packages/grpc-js-xds/src/load-balancer-xds-wrr-locality.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
// https://github.com/grpc/proposal/blob/master/A52-xds-custom-lb-policies.md
1919

20-
import { ChannelOptions, LoadBalancingConfig, experimental, logVerbosity } from "@grpc/grpc-js";
20+
import { ChannelCredentials, ChannelOptions, LoadBalancingConfig, experimental, logVerbosity } from "@grpc/grpc-js";
2121
import { loadProtosWithOptionsSync } from "@grpc/proto-loader/build/src/util";
2222
import { WeightedTargetRaw } from "./load-balancer-weighted-target";
2323
import { isLocalityEndpoint } from "./load-balancer-priority";
@@ -73,8 +73,8 @@ class XdsWrrLocalityLoadBalancingConfig implements TypedLoadBalancingConfig {
7373

7474
class XdsWrrLocalityLoadBalancer implements LoadBalancer {
7575
private childBalancer: ChildLoadBalancerHandler;
76-
constructor(private readonly channelControlHelper: ChannelControlHelper, options: ChannelOptions) {
77-
this.childBalancer = new ChildLoadBalancerHandler(channelControlHelper, options);
76+
constructor(private readonly channelControlHelper: ChannelControlHelper, credentials: ChannelCredentials, options: ChannelOptions) {
77+
this.childBalancer = new ChildLoadBalancerHandler(channelControlHelper, credentials, options);
7878
}
7979
updateAddressList(endpointList: Endpoint[], lbConfig: TypedLoadBalancingConfig, attributes: { [key: string]: unknown; }): void {
8080
if (!(lbConfig instanceof XdsWrrLocalityLoadBalancingConfig)) {

Diff for: packages/grpc-js-xds/test/test-custom-lb-policies.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { ControlPlaneServer } from "./xds-server";
2424
import * as assert from 'assert';
2525
import { WrrLocality } from "../src/generated/envoy/extensions/load_balancing_policies/wrr_locality/v3/WrrLocality";
2626
import { TypedStruct } from "../src/generated/xds/type/v3/TypedStruct";
27-
import { ChannelOptions, connectivityState, experimental, logVerbosity } from "@grpc/grpc-js";
27+
import { ChannelCredentials, ChannelOptions, connectivityState, experimental, logVerbosity } from "@grpc/grpc-js";
2828

2929
import TypedLoadBalancingConfig = experimental.TypedLoadBalancingConfig;
3030
import LoadBalancer = experimental.LoadBalancer;
@@ -84,7 +84,7 @@ const RPC_BEHAVIOR_CHILD_CONFIG = parseLoadBalancingConfig({round_robin: {}});
8484
class RpcBehaviorLoadBalancer implements LoadBalancer {
8585
private child: ChildLoadBalancerHandler;
8686
private latestConfig: RpcBehaviorLoadBalancingConfig | null = null;
87-
constructor(channelControlHelper: ChannelControlHelper, options: ChannelOptions) {
87+
constructor(channelControlHelper: ChannelControlHelper, credentials: ChannelCredentials, options: ChannelOptions) {
8888
const childChannelControlHelper = createChildChannelControlHelper(channelControlHelper, {
8989
updateState: (state, picker) => {
9090
if (state === connectivityState.READY && this.latestConfig) {
@@ -93,7 +93,7 @@ class RpcBehaviorLoadBalancer implements LoadBalancer {
9393
channelControlHelper.updateState(state, picker);
9494
}
9595
});
96-
this.child = new ChildLoadBalancerHandler(childChannelControlHelper, options);
96+
this.child = new ChildLoadBalancerHandler(childChannelControlHelper, credentials, options);
9797
}
9898
updateAddressList(endpointList: Endpoint[], lbConfig: TypedLoadBalancingConfig, attributes: { [key: string]: unknown; }): void {
9999
if (!(lbConfig instanceof RpcBehaviorLoadBalancingConfig)) {

Diff for: packages/grpc-js/src/internal-channel.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -294,13 +294,14 @@ export class InternalChannel {
294294
const channelControlHelper: ChannelControlHelper = {
295295
createSubchannel: (
296296
subchannelAddress: SubchannelAddress,
297-
subchannelArgs: ChannelOptions
297+
subchannelArgs: ChannelOptions,
298+
credentialsOverride: ChannelCredentials | null
298299
) => {
299300
const subchannel = this.subchannelPool.getOrCreateSubchannel(
300301
this.target,
301302
subchannelAddress,
302303
Object.assign({}, this.options, subchannelArgs),
303-
this.credentials
304+
credentialsOverride ?? this.credentials
304305
);
305306
subchannel.throttleKeepalive(this.keepaliveTime);
306307
if (this.channelzEnabled) {
@@ -349,6 +350,7 @@ export class InternalChannel {
349350
this.resolvingLoadBalancer = new ResolvingLoadBalancer(
350351
this.target,
351352
channelControlHelper,
353+
credentials,
352354
options,
353355
(serviceConfig, configSelector) => {
354356
if (serviceConfig.retryThrottling) {

Diff for: packages/grpc-js/src/load-balancer-child-handler.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { ConnectivityState } from './connectivity-state';
2727
import { Picker } from './picker';
2828
import type { ChannelRef, SubchannelRef } from './channelz';
2929
import { SubchannelInterface } from './subchannel-interface';
30+
import { ChannelCredentials } from './channel-credentials';
3031

3132
const TYPE_NAME = 'child_load_balancer_helper';
3233

@@ -40,11 +41,13 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
4041
constructor(private parent: ChildLoadBalancerHandler) {}
4142
createSubchannel(
4243
subchannelAddress: SubchannelAddress,
43-
subchannelArgs: ChannelOptions
44+
subchannelArgs: ChannelOptions,
45+
credentialsOverride: ChannelCredentials | null
4446
): SubchannelInterface {
4547
return this.parent.channelControlHelper.createSubchannel(
4648
subchannelAddress,
47-
subchannelArgs
49+
subchannelArgs,
50+
credentialsOverride
4851
);
4952
}
5053
updateState(connectivityState: ConnectivityState, picker: Picker): void {
@@ -86,6 +89,7 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
8689

8790
constructor(
8891
private readonly channelControlHelper: ChannelControlHelper,
92+
private readonly credentials: ChannelCredentials,
8993
private readonly options: ChannelOptions
9094
) {}
9195

@@ -114,7 +118,7 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
114118
this.configUpdateRequiresNewPolicyInstance(this.latestConfig, lbConfig)
115119
) {
116120
const newHelper = new this.ChildPolicyHelper(this);
117-
const newChild = createLoadBalancer(lbConfig, newHelper, this.options)!;
121+
const newChild = createLoadBalancer(lbConfig, newHelper, this.credentials, this.options)!;
118122
newHelper.setChild(newChild);
119123
if (this.currentChild === null) {
120124
this.currentChild = newChild;

Diff for: packages/grpc-js/src/load-balancer-outlier-detection.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
} from './subchannel-interface';
4444
import * as logging from './logging';
4545
import { LoadBalancingConfig } from './service-config';
46+
import { ChannelCredentials } from './channel-credentials';
4647

4748
const TRACER_NAME = 'outlier_detection';
4849

@@ -469,17 +470,20 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer {
469470

470471
constructor(
471472
channelControlHelper: ChannelControlHelper,
473+
credentials: ChannelCredentials,
472474
options: ChannelOptions
473475
) {
474476
this.childBalancer = new ChildLoadBalancerHandler(
475477
createChildChannelControlHelper(channelControlHelper, {
476478
createSubchannel: (
477479
subchannelAddress: SubchannelAddress,
478-
subchannelArgs: ChannelOptions
480+
subchannelArgs: ChannelOptions,
481+
credentialsOverride: ChannelCredentials | null
479482
) => {
480483
const originalSubchannel = channelControlHelper.createSubchannel(
481484
subchannelAddress,
482-
subchannelArgs
485+
subchannelArgs,
486+
credentialsOverride
483487
);
484488
const mapEntry =
485489
this.entryMap.getForSubchannelAddress(subchannelAddress);
@@ -505,6 +509,7 @@ export class OutlierDetectionLoadBalancer implements LoadBalancer {
505509
}
506510
},
507511
}),
512+
credentials,
508513
options
509514
);
510515
this.ejectionTimer = setInterval(() => {}, 0);

0 commit comments

Comments
 (0)