Start implementing XdsClient class

This commit is contained in:
Michael Lumish 2020-06-09 13:33:18 -07:00
parent 353a6e9714
commit 3fa1c098c5
7 changed files with 191 additions and 1 deletions

6
.gitmodules vendored
View File

@ -7,3 +7,9 @@
[submodule "packages/grpc-js/deps/udpa"]
path = packages/grpc-js/deps/udpa
url = https://github.com/cncf/udpa.git
[submodule "packages/grpc-js/deps/googleapis"]
path = packages/grpc-js/deps/googleapis
url = https://github.com/googleapis/googleapis.git
[submodule "packages/grpc-js/deps/protoc-gen-validate"]
path = packages/grpc-js/deps/protoc-gen-validate
url = https://github.com/envoyproxy/protoc-gen-validate.git

@ -0,0 +1 @@
Subproject commit 8c53b2cb792234354c13336ac7daee61333deade

@ -0,0 +1 @@
Subproject commit 0af61d9dc28712dc0e6f8e1a940855a2ee0cb9ed

View File

@ -0,0 +1,20 @@
#!/bin/sh
# Copyright 2020 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
base=$(dirname $0)
./node_modules/.bin/proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --json\
--includeDirs deps/envoy-api/ deps/udpa/ node_modules/protobufjs/ deps/googleapis/ deps/protoc-gen-validate/ \
-O src/generated/ --grpcLib ../index envoy/service/discovery/v2/ads.proto envoy/api/v2/listener.proto envoy/api/v2/route.proto envoy/api/v2/cluster.proto envoy/api/v2/endpoint.proto

View File

@ -15,7 +15,7 @@
"types": "build/src/index.d.ts",
"license": "Apache-2.0",
"devDependencies": {
"@grpc/proto-loader": "^0.5.4",
"@grpc/proto-loader": "^0.6.0-pre3",
"@types/gulp": "^4.0.6",
"@types/gulp-mocha": "0.0.32",
"@types/lodash": "^4.14.108",

View File

@ -0,0 +1,113 @@
/*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import * as fs from 'fs';
import * as adsTypes from './generated/ads';
/* eslint-disable @typescript-eslint/no-explicit-any */
export interface ChannelCredsConfig {
type: string;
config?: object;
}
export interface XdsServerConfig {
serverUri: string;
channelCreds: ChannelCredsConfig[];
}
export interface BootstrapInfo {
xdsServers: XdsServerConfig[];
node: adsTypes.messages.envoy.api.v2.core.Node;
}
function validateChannelCredsConfig(obj: any): ChannelCredsConfig {
if (!('type' in obj)) {
throw new Error('type field missing in xds_servers.channel_creds element');
}
if (typeof obj.type !== 'string') {
throw new Error(`xds_servers.channel_creds.type field: expected string, got ${typeof obj.type}`);
}
if ('config' in obj) {
if (typeof obj.config !== 'object' || obj.config === null) {
throw new Error('xds_servers.channel_creds config field must be an object if provided');
}
}
return {
type: obj.type,
config: obj.config
}
}
function validateXdsServerConfig(obj: any): XdsServerConfig {
if (!('server_uri' in obj)) {
throw new Error('server_uri field missing in xds_servers element');
}
if (typeof obj.server_uri !== 'string') {
throw new Error(`xds_servers.server_uri field: expected string, got ${typeof obj.server_uri}`);
}
if (!('channel_creds' in obj)) {
throw new Error('channel_creds missing in xds_servers element');
}
if (!Array.isArray(obj.channel_creds)) {
throw new Error(`xds_servers.channel_creds field: expected array, got ${typeof obj.channel_creds}`);
}
if (obj.channel_creds.length === 0) {
throw new Error('xds_servers.channel_creds field: at least one entry is required');
}
return {
serverUri: obj.server_uri,
channelCreds: obj.channel_creds.map(validateChannelCredsConfig)
};
}
function validateNode(obj: any): adsTypes.messages.envoy.api.v2.core.Node {
throw new Error('Not implemented');
}
function validateBootstrapFile(obj: any): BootstrapInfo {
return {
xdsServers: obj.xds_servers.map(validateXdsServerConfig),
node: validateNode(obj.node)
}
}
let loadedBootstrapInfo: Promise<BootstrapInfo> | null = null;
export async function loadBootstrapInfo(): Promise<BootstrapInfo> {
if (loadedBootstrapInfo !== null) {
return loadedBootstrapInfo;
}
const bootstrapPath = process.env.GRPC_XDS_BOOTSTRAP;
if (bootstrapPath === undefined) {
return Promise.reject(new Error('GRPC_XDS_BOOTSTRAP environment variable needs to be set to the path to the bootstrap file to use xDS'));
}
loadedBootstrapInfo = new Promise((resolve, reject) => {
fs.readFile(bootstrapPath, { encoding: 'utf8'}, (err, data) => {
if (err) {
reject(new Error(`Failed to read xDS bootstrap file from path ${bootstrapPath} with error ${err.message}`));
}
try {
const parsedFile = JSON.parse(data);
resolve(validateBootstrapFile(parsedFile));
} catch (e) {
reject(new Error(`Failed to parse xDS bootstrap file at path ${bootstrapPath} with error ${e.message}`));
}
});
});
return loadedBootstrapInfo;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import * as fs from 'fs';
import * as protoLoader from '@grpc/proto-loader';
import { loadPackageDefinition } from './make-client';
import * as adsTypes from './generated/ads';
import { ChannelCredentials } from './channel-credentials';
const packageDefinition = protoLoader.loadSync([
'envoy/service/discovery/v2/ads.proto',
'envoy/api/v2/listener.proto',
'envoy/api/v2/route.proto',
'envoy/api/v2/cluster.proto',
'envoy/api/v2/endpoint.proto'
], {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
includeDirs: [
'deps/envoy-api/',
'deps/udpa/',
'node_modules/protobufjs/',
'deps/googleapis/',
'deps/protoc-gen-validate/'
]
});
const loadedDefinition = loadPackageDefinition(packageDefinition) as unknown as adsTypes.ProtoGrpcType;
export class XdsClient {
}