From b501093e896a7b47800b5f8a53f2bd09cc689f54 Mon Sep 17 00:00:00 2001 From: Sheldon Kwok Date: Tue, 12 Feb 2019 10:55:22 -0800 Subject: [PATCH 1/3] Setup prettier on package.json --- .prettierignore | 1 + package-lock.json | 6 ++++++ package.json | 13 +++++++++++-- tslint.json | 1 + 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..62bc76c956 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +src/api.ts diff --git a/package-lock.json b/package-lock.json index 00f01644a7..d900726d93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2205,6 +2205,12 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, + "prettier": { + "version": "1.16.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", + "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", + "dev": true + }, "psl": { "version": "1.1.29", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", diff --git a/package.json b/package.json index 4fe631cd98..421e2c25bc 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "lint": "tslint --project \".\"", + "format": "prettier --loglevel error --write './src/**/*.ts'", + "lint": "tslint --project \".\" && prettier --check './src/**/*.ts'", "lint-examples": "tslint --project \"./examples/typescript\"", "clean": "rm -Rf node_modules/ dist/", "build": "tsc", @@ -71,6 +72,7 @@ "mocha": "^5.2.0", "mock-fs": "^4.7.0", "nyc": "^13.1.0", + "prettier": "~1.16.4", "source-map-support": "^0.5.9", "stream-buffers": "^3.0.2", "ts-mockito": "^2.3.1", @@ -85,5 +87,12 @@ "keywords": [ "kubernetes", "client" - ] + ], + "prettier": { + "tabWidth": 4, + "printWidth": 110, + "trailingComma": "all", + "singleQuote": true, + "arrowParens": "always" + } } diff --git a/tslint.json b/tslint.json index fee6086099..f0e7fabf3b 100644 --- a/tslint.json +++ b/tslint.json @@ -13,6 +13,7 @@ "quotemark": [true, "single", "avoid-escape", "avoid-template"], "interface-name": [true, "never-prefix"], "object-literal-sort-keys": false, + "object-literal-key-quotes": [true, "as-needed"], "max-classes-per-file": false }, "rulesDirectory": [] From 25197421fc7752c510af292e1367d0351274af48 Mon Sep 17 00:00:00 2001 From: Sheldon Kwok Date: Tue, 5 Feb 2019 13:24:47 -0800 Subject: [PATCH 2/3] Run prettier on code base --- src/attach.ts | 24 +++++++---- src/attach_test.ts | 18 +++----- src/cache.ts | 20 +++++---- src/cache_test.ts | 8 ++-- src/cloud_auth.ts | 5 +-- src/config.ts | 43 +++++++++---------- src/config_test.ts | 77 +++++++++++++++++++--------------- src/config_types.ts | 2 +- src/exec.ts | 37 ++++++++++------ src/exec_auth.ts | 7 ++-- src/exec_test.ts | 45 +++++++++++--------- src/oidc_auth_test.ts | 3 +- src/portforward.ts | 48 +++++++++++---------- src/portforward_test.ts | 12 ++---- src/watch.ts | 9 ++-- src/watch_test.ts | 23 ++++++---- src/web-socket-handler.ts | 26 ++++++------ src/web-socket-handler_test.ts | 49 +++++++++++++++------- src/yaml_test.ts | 30 +++++++------ 19 files changed, 267 insertions(+), 219 deletions(-) diff --git a/src/attach.ts b/src/attach.ts index 6e1d775625..da69774b6a 100644 --- a/src/attach.ts +++ b/src/attach.ts @@ -16,9 +16,15 @@ export class Attach { } } - public async attach(namespace: string, podName: string, containerName: string, - stdout: stream.Writable | any, stderr: stream.Writable | any, stdin: stream.Readable | any, - tty: boolean): Promise { + public async attach( + namespace: string, + podName: string, + containerName: string, + stdout: stream.Writable | any, + stderr: stream.Writable | any, + stdin: stream.Readable | any, + tty: boolean, + ): Promise { const query = { container: containerName, stderr: stderr != null, @@ -28,10 +34,14 @@ export class Attach { }; const queryStr = querystring.stringify(query); const path = `/api/v1/namespaces/${namespace}/pods/${podName}/attach?${queryStr}`; - const conn = await this.handler.connect(path, null, (streamNum: number, buff: Buffer): boolean => { - WebSocketHandler.handleStandardStreams(streamNum, buff, stdout, stderr); - return true; - }); + const conn = await this.handler.connect( + path, + null, + (streamNum: number, buff: Buffer): boolean => { + WebSocketHandler.handleStandardStreams(streamNum, buff, stdout, stderr); + return true; + }, + ); if (stdin != null) { WebSocketHandler.handleStandardInput(conn, stdin); } diff --git a/src/attach_test.ts b/src/attach_test.ts index 41399f0135..05382a9de8 100644 --- a/src/attach_test.ts +++ b/src/attach_test.ts @@ -21,30 +21,25 @@ describe('Attach', () => { const pod = 'somepod'; const container = 'somecontainer'; - await attach.attach( - namespace, pod, container, osStream, errStream, isStream, false); + await attach.attach(namespace, pod, container, osStream, errStream, isStream, false); const path = `/api/v1/namespaces/${namespace}/pods/${pod}/attach`; let args = `container=${container}&stderr=true&stdin=true&stdout=true&tty=false`; verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await attach.attach( - namespace, pod, container, null, null, null, false); + await attach.attach(namespace, pod, container, null, null, null, false); args = `container=${container}&stderr=false&stdin=false&stdout=false&tty=false`; verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await attach.attach( - namespace, pod, container, osStream, null, null, false); + await attach.attach(namespace, pod, container, osStream, null, null, false); args = `container=${container}&stderr=false&stdin=false&stdout=true&tty=false`; verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await attach.attach( - namespace, pod, container, osStream, errStream, null, false); + await attach.attach(namespace, pod, container, osStream, errStream, null, false); args = `container=${container}&stderr=true&stdin=false&stdout=true&tty=false`; verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await attach.attach( - namespace, pod, container, osStream, errStream, null, true); + await attach.attach(namespace, pod, container, osStream, errStream, null, true); args = `container=${container}&stderr=true&stdin=false&stdout=true&tty=true`; verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); }); @@ -67,8 +62,7 @@ describe('Attach', () => { const fakeConn: WebSocket = mock(WebSocket); when(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).thenResolve(fakeConn); - await attach.attach( - namespace, pod, container, osStream, errStream, isStream, false); + await attach.attach(namespace, pod, container, osStream, errStream, isStream, false); const [, , outputFn] = capture(fakeWebSocket.connect).last(); /* tslint:disable:no-unused-expression */ diff --git a/src/cache.ts b/src/cache.ts index e8de629f43..22874f0445 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -12,19 +12,22 @@ export class ListWatch implements ObjectCache { private objects: T[] = []; private readonly indexCache: { [key: string]: T[] } = {}; - public constructor(private readonly path: string, - private readonly watch: Watch, - private readonly listFn: (callback: ListCallback) => void) { + public constructor( + private readonly path: string, + private readonly watch: Watch, + private readonly listFn: (callback: ListCallback) => void, + ) { this.watch = watch; this.listFn = listFn; this.doneHandler(null); } public get(name: string, namespace?: string): T | undefined { - return this.objects.find((obj: T): boolean => { - return (obj.metadata.name === name && - (!namespace || obj.metadata.namespace === namespace)); - }); + return this.objects.find( + (obj: T): boolean => { + return obj.metadata.name === name && (!namespace || obj.metadata.namespace === namespace); + }, + ); } public list(namespace?: string | undefined): ReadonlyArray { @@ -86,8 +89,7 @@ export function addOrUpdateObject(objects: T[], obj: } function isSameObject(o1: T, o2: T): boolean { - return o1.metadata.name === o2.metadata.name && - o1.metadata.namespace === o2.metadata.namespace; + return o1.metadata.name === o2.metadata.name && o1.metadata.namespace === o2.metadata.namespace; } function findKubernetesObject(objects: T[], obj: T): number { diff --git a/src/cache_test.ts b/src/cache_test.ts index 88ed5f212b..ad66a90fa4 100644 --- a/src/cache_test.ts +++ b/src/cache_test.ts @@ -31,7 +31,7 @@ describe('ListWatchCache', () => { expect(cache.get('name1')).to.equal(list[0]); expect(cache.get('name2')).to.equal(list[1]); - watchHandler('ADDED', { + watchHandler('ADDED', { metadata: { name: 'name3', } as V1ObjectMeta, @@ -40,7 +40,7 @@ describe('ListWatchCache', () => { expect(cache.list().length).to.equal(3); expect(cache.get('name3')).to.not.equal(null); - watchHandler('MODIFIED', { + watchHandler('MODIFIED', { metadata: { name: 'name3', resourceVersion: 'baz', @@ -96,7 +96,7 @@ describe('ListWatchCache', () => { expect(cache.list('ns2').length).to.equal(1); expect(cache.list('ns2')[0].metadata.name).to.equal('name2'); - watchHandler('ADDED', { + watchHandler('ADDED', { metadata: { name: 'name3', namespace: 'ns3', @@ -106,7 +106,7 @@ describe('ListWatchCache', () => { expect(cache.list().length).to.equal(3); expect(cache.get('name3', 'ns3')).to.not.equal(null); - watchHandler('MODIFIED', { + watchHandler('MODIFIED', { metadata: { name: 'name3', namespace: 'ns3', diff --git a/src/cloud_auth.ts b/src/cloud_auth.ts index 48004f6b7f..80b078dd62 100644 --- a/src/cloud_auth.ts +++ b/src/cloud_auth.ts @@ -19,10 +19,7 @@ interface Config { } export class CloudAuth implements Authenticator { public isAuthProvider(user: User): boolean { - return ( - user.authProvider.name === 'azure' || - user.authProvider.name === 'gcp' - ); + return user.authProvider.name === 'azure' || user.authProvider.name === 'gcp'; } public getToken(user: User): string | null { diff --git a/src/config.ts b/src/config.ts index a2ae4d47fe..8fd3da9530 100644 --- a/src/config.ts +++ b/src/config.ts @@ -17,16 +17,13 @@ function fileExists(filepath: string): boolean { try { fs.accessSync(filepath); return true; - // tslint:disable-next-line:no-empty - } catch (ignore) { } + // tslint:disable-next-line:no-empty + } catch (ignore) {} return false; } export class KubeConfig { - private static authenticators: Authenticator[] = [ - new CloudAuth(), - new ExecAuth(), - ]; + private static authenticators: Authenticator[] = [new CloudAuth(), new ExecAuth()]; /** * The list of all known clusters @@ -213,7 +210,9 @@ export class KubeConfig { } if (process.platform === 'win32' && shelljs.which('wsl.exe')) { // TODO: Handle if someome set $KUBECONFIG in wsl here... - const result = shelljs.exec('wsl.exe cat $HOME/.kube/config', { silent: true }); + const result = shelljs.exec('wsl.exe cat $HOME/.kube/config', { + silent: true, + }); if (result.code === 0) { this.loadFromString(result.stdout); return; @@ -278,12 +277,11 @@ export class KubeConfig { let token: string | null = null; if (user.authProvider && user.authProvider.config) { - KubeConfig.authenticators.forEach( - (authenticator: Authenticator) => { - if (authenticator.isAuthProvider(user)) { - token = authenticator.getToken(user); - } - }); + KubeConfig.authenticators.forEach((authenticator: Authenticator) => { + if (authenticator.isAuthProvider(user)) { + token = authenticator.getToken(user); + } + }); } if (user.token) { @@ -309,17 +307,14 @@ export interface ApiType { } export interface ApiConstructor { - new(server: string): T; + new (server: string): T; } // This class is deprecated and will eventually be removed. export class Config { - public static SERVICEACCOUNT_ROOT = - '/var/run/secrets/kubernetes.io/serviceaccount'; - public static SERVICEACCOUNT_CA_PATH = - Config.SERVICEACCOUNT_ROOT + '/ca.crt'; - public static SERVICEACCOUNT_TOKEN_PATH = - Config.SERVICEACCOUNT_ROOT + '/token'; + public static SERVICEACCOUNT_ROOT = '/var/run/secrets/kubernetes.io/serviceaccount'; + public static SERVICEACCOUNT_CA_PATH = Config.SERVICEACCOUNT_ROOT + '/ca.crt'; + public static SERVICEACCOUNT_TOKEN_PATH = Config.SERVICEACCOUNT_ROOT + '/token'; public static fromFile(filename: string): api.Core_v1Api { return Config.apiFromFile(filename, api.Core_v1Api); @@ -362,7 +357,7 @@ export class Config { } // This is public really only for testing. -export function bufferFromFileOrString(file ?: string, data ?: string): Buffer | null { +export function bufferFromFileOrString(file?: string, data?: string): Buffer | null { if (file) { return fs.readFileSync(file); } @@ -379,7 +374,7 @@ export function findHomeDir(): string | null { fs.accessSync(process.env.HOME); return process.env.HOME; // tslint:disable-next-line:no-empty - } catch (ignore) { } + } catch (ignore) {} } if (process.platform !== 'win32') { return null; @@ -390,13 +385,13 @@ export function findHomeDir(): string | null { fs.accessSync(dir); return dir; // tslint:disable-next-line:no-empty - } catch (ignore) { } + } catch (ignore) {} } if (process.env.USERPROFILE) { try { fs.accessSync(process.env.USERPROFILE); return process.env.USERPROFILE; - // tslint:disable-next-line:no-empty + // tslint:disable-next-line:no-empty } catch (ignore) {} } return null; diff --git a/src/config_test.ts b/src/config_test.ts index 24b6719a0e..b11e3b359c 100644 --- a/src/config_test.ts +++ b/src/config_test.ts @@ -14,7 +14,7 @@ const kcFileName = 'testdata/kubeconfig.yaml'; const kcNoUserFileName = 'testdata/empty-user-kubeconfig.yaml'; /* tslint:disable: no-empty */ -describe('Config', () => { }); +describe('Config', () => {}); function validateFileLoad(kc: KubeConfig) { // check clusters @@ -256,8 +256,7 @@ describe('KubeConfig', () => { newUsers([ { name: 'some-user', - user: { - }, + user: {}, }, { foo: 'bar', @@ -326,8 +325,8 @@ describe('KubeConfig', () => { 'client-certificate': certFile, 'client-key-data': keyData, 'client-key': keyFile, - 'password': password, - 'username': username, + password, + username, }, }, ]); @@ -506,7 +505,8 @@ describe('KubeConfig', () => { { username: user, password: passwd, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -522,9 +522,7 @@ describe('KubeConfig', () => { it('should not populate strict ssl', () => { const config = new KubeConfig(); - config.loadFromClusterAndUser( - { skipTLSVerify: false } as Cluster, - {} as User); + config.loadFromClusterAndUser({ skipTLSVerify: false } as Cluster, {} as User); const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -538,7 +536,8 @@ describe('KubeConfig', () => { { skipTLSVerify: false } as Cluster, { token, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -557,10 +556,11 @@ describe('KubeConfig', () => { name: 'azure', config: { 'access-token': token, - 'expiry': 'Fri Aug 24 07:32:05 PDT 3018', + expiry: 'Fri Aug 24 07:32:05 PDT 3018', }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -586,7 +586,8 @@ describe('KubeConfig', () => { 'access-token': token, }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -608,7 +609,8 @@ describe('KubeConfig', () => { 'access-token': token, }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -621,7 +623,7 @@ describe('KubeConfig', () => { const config = new KubeConfig(); const token = 'token'; config.loadFromClusterAndUser( - { } as Cluster, + {} as Cluster, { authProvider: { name: 'azure', @@ -629,7 +631,8 @@ describe('KubeConfig', () => { 'access-token': token, }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -647,7 +650,8 @@ describe('KubeConfig', () => { expiry: 'Aug 24 07:32:05 PDT 2017', }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; expect(() => config.applyToRequest(opts)).to.throw('Token is expired!'); @@ -662,14 +666,14 @@ describe('KubeConfig', () => { name: 'azure', config: { 'access-token': 'token', - 'expiry': 'Aug 24 07:32:05 PDT 2017', + expiry: 'Aug 24 07:32:05 PDT 2017', 'cmd-path': 'non-existent-command', }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; - expect(() => config.applyToRequest(opts)).to.throw( - /Failed to refresh token/); + expect(() => config.applyToRequest(opts)).to.throw(/Failed to refresh token/); }); it('should exec with expired token', () => { @@ -682,14 +686,15 @@ describe('KubeConfig', () => { authProvider: { name: 'azure', config: { - 'expiry': 'Aug 24 07:32:05 PDT 2017', + expiry: 'Aug 24 07:32:05 PDT 2017', 'cmd-path': 'echo', 'cmd-args': `'${responseStr}'`, 'token-key': '{.token.accessToken}', 'expiry-key': '{.token.token_expiry}', }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); expect(opts.headers).to.not.be.undefined; @@ -713,7 +718,8 @@ describe('KubeConfig', () => { 'expiry-key': '{.token.token_expiry}', }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); expect(opts.headers).to.not.be.undefined; @@ -737,7 +743,8 @@ describe('KubeConfig', () => { 'expiry-key': '{.token.token_expiry}', }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; config.applyToRequest(opts); expect(opts.headers).to.not.be.undefined; @@ -767,7 +774,8 @@ describe('KubeConfig', () => { }, }, }, - } as User); + } as User, + ); // TODO: inject the exec command here and validate env vars? const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -798,7 +806,8 @@ describe('KubeConfig', () => { }, }, }, - } as User); + } as User, + ); // TODO: inject the exec command here? const opts = {} as requestlib.Options; config.applyToRequest(opts); @@ -815,13 +824,15 @@ describe('KubeConfig', () => { authProvider: { name: 'exec', config: { - exec: { - }, + exec: {}, }, }, - } as User); + } as User, + ); const opts = {} as requestlib.Options; - expect(() => config.applyToRequest(opts)).to.throw('No command was specified for exec authProvider!'); + expect(() => config.applyToRequest(opts)).to.throw( + 'No command was specified for exec authProvider!', + ); }); }); @@ -859,7 +870,7 @@ describe('KubeConfig', () => { mockfs({ '/var/run/secrets/kubernetes.io/serviceaccount': { 'ca.crt': cert, - 'token': token, + token, }, }); @@ -892,7 +903,7 @@ describe('KubeConfig', () => { mockfs({ '/var/run/secrets/kubernetes.io/serviceaccount': { 'ca.crt': cert, - 'token': token, + token, }, }); diff --git a/src/config_types.ts b/src/config_types.ts index e25eed7db0..eeb9204b6f 100644 --- a/src/config_types.ts +++ b/src/config_types.ts @@ -60,7 +60,7 @@ function userIterator(): u.ListIterator { certData: elt.user ? elt.user['client-certificate-data'] : null, certFile: elt.user ? elt.user['client-certificate'] : null, keyData: elt.user ? elt.user['client-key-data'] : null, - keyFile: elt.user ? elt.user['client-key'] : null, + keyFile: elt.user ? elt.user['client-key'] : null, name: elt.name, token: findToken(elt.user), password: elt.user ? elt.user.password : null, diff --git a/src/exec.ts b/src/exec.ts index d1f8d92d43..31454696b4 100644 --- a/src/exec.ts +++ b/src/exec.ts @@ -30,10 +30,17 @@ export class Exec { * A callback to received the status (e.g. exit code) from the command, optional. * @return {string} This is the result */ - public async exec(namespace: string, podName: string, containerName: string, command: string | string[], - stdout: stream.Writable | null, stderr: stream.Writable | null, stdin: stream.Readable | null, - tty: boolean, - statusCallback?: (status: V1Status) => void): Promise { + public async exec( + namespace: string, + podName: string, + containerName: string, + command: string | string[], + stdout: stream.Writable | null, + stderr: stream.Writable | null, + stdin: stream.Readable | null, + tty: boolean, + statusCallback?: (status: V1Status) => void, + ): Promise { const query = { stdout: stdout != null, stderr: stderr != null, @@ -44,16 +51,20 @@ export class Exec { }; const queryStr = querystring.stringify(query); const path = `/api/v1/namespaces/${namespace}/pods/${podName}/exec?${queryStr}`; - const conn = await this.handler.connect(path, null, (streamNum: number, buff: Buffer): boolean => { - const status = WebSocketHandler.handleStandardStreams(streamNum, buff, stdout, stderr); - if (status != null) { - if (statusCallback) { - statusCallback(status); + const conn = await this.handler.connect( + path, + null, + (streamNum: number, buff: Buffer): boolean => { + const status = WebSocketHandler.handleStandardStreams(streamNum, buff, stdout, stderr); + if (status != null) { + if (statusCallback) { + statusCallback(status); + } + return false; } - return false; - } - return true; - }); + return true; + }, + ); if (stdin != null) { WebSocketHandler.handleStandardInput(conn, stdin); } diff --git a/src/exec_auth.ts b/src/exec_auth.ts index 0dab9f8436..c4fada7ba9 100644 --- a/src/exec_auth.ts +++ b/src/exec_auth.ts @@ -7,8 +7,9 @@ export class ExecAuth implements Authenticator { private readonly tokenCache: { [key: string]: any } = {}; public isAuthProvider(user: User) { - return user.authProvider.name === 'exec' || - (user.authProvider.config && user.authProvider.config.exec); + return ( + user.authProvider.name === 'exec' || (user.authProvider.config && user.authProvider.config.exec) + ); } public getToken(user: User): string | null { @@ -35,7 +36,7 @@ export class ExecAuth implements Authenticator { let opts: shell.ExecOpts; if (config.exec.env) { const env = {}; - config.exec.env.forEach((elt) => env[elt.name] = elt.value); + config.exec.env.forEach((elt) => (env[elt.name] = elt.value)); opts = { env }; } const result = shell.exec(cmd, opts); diff --git a/src/exec_test.ts b/src/exec_test.ts index 5361950ed6..b07ced34e1 100644 --- a/src/exec_test.ts +++ b/src/exec_test.ts @@ -25,35 +25,31 @@ describe('Exec', () => { const cmdArray = ['command', 'arg1', 'arg2']; const path = `/api/v1/namespaces/${namespace}/pods/${pod}/exec`; - await exec.exec( - namespace, pod, container, cmd, osStream, errStream, isStream, false); + await exec.exec(namespace, pod, container, cmd, osStream, errStream, isStream, false); let args = `stdout=true&stderr=true&stdin=true&tty=false&command=${cmd}&container=${container}`; - verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); + verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await exec.exec( - namespace, pod, container, cmd, null, errStream, isStream, false); + await exec.exec(namespace, pod, container, cmd, null, errStream, isStream, false); args = `stdout=false&stderr=true&stdin=true&tty=false&command=${cmd}&container=${container}`; - verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); + verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await exec.exec( - namespace, pod, container, cmd, null, null, isStream, false); + await exec.exec(namespace, pod, container, cmd, null, null, isStream, false); args = `stdout=false&stderr=false&stdin=true&tty=false&command=${cmd}&container=${container}`; - verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); + verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await exec.exec( - namespace, pod, container, cmd, null, null, null, false); + await exec.exec(namespace, pod, container, cmd, null, null, null, false); args = `stdout=false&stderr=false&stdin=false&tty=false&command=${cmd}&container=${container}`; - verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); + verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await exec.exec( - namespace, pod, container, cmd, null, errStream, isStream, true); + await exec.exec(namespace, pod, container, cmd, null, errStream, isStream, true); args = `stdout=false&stderr=true&stdin=true&tty=true&command=${cmd}&container=${container}`; - verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); + verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); - await exec.exec( - namespace, pod, container, cmdArray, null, errStream, isStream, true); + await exec.exec(namespace, pod, container, cmdArray, null, errStream, isStream, true); // tslint:disable-next-line:max-line-length - args = `stdout=false&stderr=true&stdin=true&tty=true&command=${cmdArray[0]}&command=${cmdArray[1]}&command=${cmdArray[2]}&container=${container}`; + args = `stdout=false&stderr=true&stdin=true&tty=true&command=${cmdArray[0]}&command=${ + cmdArray[1] + }&command=${cmdArray[2]}&container=${container}`; verify(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).called(); }); @@ -79,9 +75,18 @@ describe('Exec', () => { when(fakeWebSocket.connect(`${path}?${args}`, null, anyFunction())).thenResolve(fakeConn); await exec.exec( - namespace, pod, container, cmd, osStream, errStream, isStream, false, (status: V1Status) => { + namespace, + pod, + container, + cmd, + osStream, + errStream, + isStream, + false, + (status: V1Status) => { statusOut = status; - }); + }, + ); const [, , outputFn] = capture(fakeWebSocket.connect).last(); diff --git a/src/oidc_auth_test.ts b/src/oidc_auth_test.ts index c3dd342b6b..afb3c7e559 100644 --- a/src/oidc_auth_test.ts +++ b/src/oidc_auth_test.ts @@ -49,8 +49,7 @@ describe('OIDCAuth', () => { const user = { authProvider: { name: 'oidc', - config: { - }, + config: {}, }, } as User; diff --git a/src/portforward.ts b/src/portforward.ts index 7d7cde8bd0..02d3c01b9d 100644 --- a/src/portforward.ts +++ b/src/portforward.ts @@ -22,16 +22,18 @@ export class PortForward { // TODO: support multiple ports for real... public async portForward( - namespace: string, podName: string, targetPorts: number[], - output: stream.Writable, err: stream.Writable | null, + namespace: string, + podName: string, + targetPorts: number[], + output: stream.Writable, + err: stream.Writable | null, input: stream.Readable, ): Promise { - if (targetPorts.length === 0) { throw new Error('You must provide at least one port to forward to.'); } if (targetPorts.length > 1) { - throw(new Error('Only one port is currently supported for port-forward')); + throw new Error('Only one port is currently supported for port-forward'); } const query = { ports: targetPorts[0], @@ -43,24 +45,28 @@ export class PortForward { needsToReadPortNumber[index * 2 + 1] = true; }); const path = `/api/v1/namespaces/${namespace}/pods/${podName}/portforward?${queryStr}`; - const conn = await this.handler.connect(path, null, (streamNum: number, buff: Buffer | string): boolean => { - if (streamNum >= targetPorts.length * 2) { - return !this.disconnectOnErr; - } - // First two bytes of each stream are the port number - if (needsToReadPortNumber[streamNum]) { - buff = buff.slice(2); - needsToReadPortNumber[streamNum] = false; - } - if (streamNum % 2 === 1) { - if (err) { - err.write(buff); + const conn = await this.handler.connect( + path, + null, + (streamNum: number, buff: Buffer | string): boolean => { + if (streamNum >= targetPorts.length * 2) { + return !this.disconnectOnErr; } - } else { - output.write(buff); - } - return true; - }); + // First two bytes of each stream are the port number + if (needsToReadPortNumber[streamNum]) { + buff = buff.slice(2); + needsToReadPortNumber[streamNum] = false; + } + if (streamNum % 2 === 1) { + if (err) { + err.write(buff); + } + } else { + output.write(buff); + } + return true; + }, + ); WebSocketHandler.handleStandardInput(conn, input, 0); return conn; } diff --git a/src/portforward_test.ts b/src/portforward_test.ts index 28360e6f15..024db2e878 100644 --- a/src/portforward_test.ts +++ b/src/portforward_test.ts @@ -19,8 +19,7 @@ describe('PortForward', () => { const pod = 'somepod'; const port = 8080; - await portForward.portForward( - namespace, pod, [port], osStream, errStream, isStream); + await portForward.portForward(namespace, pod, [port], osStream, errStream, isStream); const path = `/api/v1/namespaces/${namespace}/pods/${pod}/portforward?ports=${port}`; verify(fakeWebSocket.connect(path, null, anyFunction())).called(); @@ -33,8 +32,7 @@ describe('PortForward', () => { const osStream = new WritableStreamBuffer(); const isStream = new ReadableStreamBuffer(); - const conn = await portForward.portForward( - 'ns', 'p', [8000], osStream, null, isStream); + const conn = await portForward.portForward('ns', 'p', [8000], osStream, null, isStream); const [, , outputFn] = capture(fakeWebSocket.connect).last(); @@ -61,8 +59,7 @@ describe('PortForward', () => { const osStream = new WritableStreamBuffer(); const isStream = new ReadableStreamBuffer(); - await portForward.portForward( - 'ns', 'p', [8000], osStream, null, isStream); + await portForward.portForward('ns', 'p', [8000], osStream, null, isStream); const [, , outputFn] = capture(fakeWebSocket.connect).last(); @@ -88,8 +85,7 @@ describe('PortForward', () => { const errStream = new WritableStreamBuffer(); const isStream = new ReadableStreamBuffer(); - await portForward.portForward( - 'ns', 'p', [8000], osStream, errStream, isStream); + await portForward.portForward('ns', 'p', [8000], osStream, errStream, isStream); const [, , outputFn] = capture(fakeWebSocket.connect).last(); diff --git a/src/watch.ts b/src/watch.ts index 2a346173bc..d51e5e5c9e 100644 --- a/src/watch.ts +++ b/src/watch.ts @@ -30,9 +30,12 @@ export class Watch { } } - public watch(path: string, queryParams: any, - callback: (phase: string, obj: any) => void, - done: (err: any) => void): any { + public watch( + path: string, + queryParams: any, + callback: (phase: string, obj: any) => void, + done: (err: any) => void, + ): any { const cluster = this.config.getCurrentCluster(); if (!cluster) { throw new Error('No currently active cluster'); diff --git a/src/watch_test.ts b/src/watch_test.ts index 237df5b293..cea02390ff 100644 --- a/src/watch_test.ts +++ b/src/watch_test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import request = require('request'); import { ReadableStreamBuffer, WritableStreamBuffer } from 'stream-buffers'; -import { anyFunction, anything, capture, instance, mock, reset, verify, when } from 'ts-mockito'; +import { anyFunction, anything, capture, instance, mock, reset, verify, when } from 'ts-mockito'; import { KubeConfig } from './config'; import { Cluster, Context, User } from './config_types'; @@ -66,13 +66,18 @@ describe('Watch', () => { let doneCalled = false; let doneErr: any; - watch.watch(path, {}, (phase: string, obj: string) => { - receivedTypes.push(phase); - receivedObjects.push(obj); - }, (err: any) => { - doneCalled = true; - doneErr = err; - }); + watch.watch( + path, + {}, + (phase: string, obj: string) => { + receivedTypes.push(phase); + receivedObjects.push(obj); + }, + (err: any) => { + doneCalled = true; + doneErr = err; + }, + ); verify(fakeRequestor.webRequest(anything(), anyFunction())); @@ -93,7 +98,7 @@ describe('Watch', () => { expect(doneCalled).to.equal(true); expect(doneErr).to.equal(null); - const errIn = {error: 'err'}; + const errIn = { error: 'err' }; doneCallback(errIn, null, null); expect(doneErr).to.deep.equal(errIn); }); diff --git a/src/web-socket-handler.ts b/src/web-socket-handler.ts index 81d200037c..a9f59a04a7 100644 --- a/src/web-socket-handler.ts +++ b/src/web-socket-handler.ts @@ -4,12 +4,7 @@ import stream = require('stream'); import { V1Status } from './api'; import { KubeConfig } from './config'; -const protocols = [ - 'v4.channel.k8s.io', - 'v3.channel.k8s.io', - 'v2.channel.k8s.io', - 'channel.k8s.io', -]; +const protocols = ['v4.channel.k8s.io', 'v3.channel.k8s.io', 'v2.channel.k8s.io', 'channel.k8s.io']; export interface WebSocketInterface { connect( @@ -26,8 +21,10 @@ export class WebSocketHandler implements WebSocketInterface { public static readonly StatusStream = 3; public static handleStandardStreams( - streamNum: number, buff: Buffer, - stdout: stream.Writable | null, stderr: stream.Writable | null, + streamNum: number, + buff: Buffer, + stdout: stream.Writable | null, + stderr: stream.Writable | null, ): V1Status | null { if (buff.length < 1) { return null; @@ -75,10 +72,10 @@ export class WebSocketHandler implements WebSocketInterface { } // factory is really just for test injection - public constructor(readonly config: KubeConfig, - readonly socketFactory?: - (uri: string, opts: WebSocket.ClientOptions) => WebSocket) { - } + public constructor( + readonly config: KubeConfig, + readonly socketFactory?: (uri: string, opts: WebSocket.ClientOptions) => WebSocket, + ) {} /** * Connect to a web socket endpoint. @@ -93,7 +90,6 @@ export class WebSocketHandler implements WebSocketInterface { textHandler: ((text: string) => boolean) | null, binaryHandler: ((stream: number, buff: Buffer) => boolean) | null, ): Promise { - const cluster = this.config.getCurrentCluster(); if (!cluster) { throw new Error('No cluster is defined.'); @@ -109,7 +105,9 @@ export class WebSocketHandler implements WebSocketInterface { this.config.applytoHTTPSOptions(opts); return new Promise((resolve, reject) => { - const client = (this.socketFactory ? this.socketFactory(uri, opts) : new WebSocket(uri, protocols, opts)); + const client = this.socketFactory + ? this.socketFactory(uri, opts) + : new WebSocket(uri, protocols, opts); let resolved = false; client.onopen = () => { diff --git a/src/web-socket-handler_test.ts b/src/web-socket-handler_test.ts index bbfc66f6de..7d99c93089 100644 --- a/src/web-socket-handler_test.ts +++ b/src/web-socket-handler_test.ts @@ -15,8 +15,9 @@ describe('WebSocket', () => { const buff = Buffer.alloc(30, 20); const badStream = 10; - expect(() => WebSocketHandler.handleStandardStreams(badStream, buff, osStream, errStream)) - .to.throw(`Unknown stream: ${badStream}`); + expect(() => WebSocketHandler.handleStandardStreams(badStream, buff, osStream, errStream)).to.throw( + `Unknown stream: ${badStream}`, + ); }); it('should handle a status to end', () => { const osStream = new WritableStreamBuffer(); @@ -30,7 +31,12 @@ describe('WebSocket', () => { const buff = Buffer.alloc(data.length); buff.write(data); - const output = WebSocketHandler.handleStandardStreams(WebSocketHandler.StatusStream, buff, osStream, errStream); + const output = WebSocketHandler.handleStandardStreams( + WebSocketHandler.StatusStream, + buff, + osStream, + errStream, + ); expect(osStream.size()).to.equal(0); expect(errStream.size()).to.equal(0); @@ -106,10 +112,13 @@ describe('WebSocket', () => { const mockWs = {} as WebSocket; let uriOut = ''; - const handler = new WebSocketHandler(kc, (uri: string, opts: WebSocket.ClientOptions): WebSocket => { - uriOut = uri; - return mockWs as WebSocket; - }); + const handler = new WebSocketHandler( + kc, + (uri: string, opts: WebSocket.ClientOptions): WebSocket => { + uriOut = uri; + return mockWs as WebSocket; + }, + ); const path = '/some/path'; const promise = handler.connect(path, null, null); @@ -154,10 +163,13 @@ describe('WebSocket', () => { const mockWs = {} as WebSocket; let uriOut = ''; - const handler = new WebSocketHandler(kc, (uri: string, opts: WebSocket.ClientOptions): WebSocket => { - uriOut = uri; - return mockWs as WebSocket; - }); + const handler = new WebSocketHandler( + kc, + (uri: string, opts: WebSocket.ClientOptions): WebSocket => { + uriOut = uri; + return mockWs as WebSocket; + }, + ); const path = '/some/path'; const promise = handler.connect(path, null, null); @@ -212,14 +224,19 @@ describe('WebSocket', () => { let closeCount = 0; const mockWs = { - close: () => { closeCount++; }, + close: () => { + closeCount++; + }, } as WebSocket; let uriOut = ''; - const handler = new WebSocketHandler(kc, (uri: string, opts: WebSocket.ClientOptions): WebSocket => { - uriOut = uri; - return mockWs as WebSocket; - }); + const handler = new WebSocketHandler( + kc, + (uri: string, opts: WebSocket.ClientOptions): WebSocket => { + uriOut = uri; + return mockWs as WebSocket; + }, + ); const path = '/some/path'; let textReceived = ''; diff --git a/src/yaml_test.ts b/src/yaml_test.ts index 414881f72f..58657a68e7 100644 --- a/src/yaml_test.ts +++ b/src/yaml_test.ts @@ -5,10 +5,7 @@ import { dumpYaml, loadAllYaml, loadYaml } from './yaml'; describe('yaml', () => { it('should load safely', () => { - const yaml = 'apiVersion: v1\n' + - 'kind: Namespace\n' + - 'metadata:\n' + - ' name: some-namespace\n'; + const yaml = 'apiVersion: v1\n' + 'kind: Namespace\n' + 'metadata:\n' + ' name: some-namespace\n'; const ns = loadYaml(yaml); expect(ns.apiVersion).to.equal('v1'); @@ -16,16 +13,17 @@ describe('yaml', () => { expect(ns.metadata.name).to.equal('some-namespace'); }); it('should load all safely', () => { - const yaml = 'apiVersion: v1\n' + - 'kind: Namespace\n' + - 'metadata:\n' + - ' name: some-namespace\n' + - '---\n' + - 'apiVersion: v1\n' + - 'kind: Pod\n' + - 'metadata:\n' + - ' name: some-pod\n' + - ' namespace: some-ns\n'; + const yaml = + 'apiVersion: v1\n' + + 'kind: Namespace\n' + + 'metadata:\n' + + ' name: some-namespace\n' + + '---\n' + + 'apiVersion: v1\n' + + 'kind: Pod\n' + + 'metadata:\n' + + ' name: some-pod\n' + + ' namespace: some-ns\n'; const objects = loadAllYaml(yaml); expect(objects.length).to.equal(2); @@ -38,9 +36,9 @@ describe('yaml', () => { it('should round trip successfully', () => { const expected = { metadata: { - name: 'test', + name: 'test', }, - }; + }; const yamlString = dumpYaml(expected); const actual = loadYaml(yamlString); expect(actual).to.deep.equal(expected); From 43466f1c214e406d1dade5d343d6ee89cba8acb2 Mon Sep 17 00:00:00 2001 From: Sheldon Kwok Date: Tue, 12 Feb 2019 11:18:39 -0800 Subject: [PATCH 3/3] Add to readme for formatting and linting --- README.md | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 1e9df3cc4e..d0704933ba 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ [![Client Capabilities](https://img.shields.io/badge/Kubernetes%20client-Silver-blue.svg?style=flat&colorB=C0C0C0&colorA=306CE8)](http://bit.ly/kubernetes-client-capabilities-badge) [![Client Support Level](https://img.shields.io/badge/kubernetes%20client-beta-green.svg?style=flat&colorA=306CE8)](http://bit.ly/kubernetes-client-support-badge) - The Javascript clients for Kubernetes is implemented in [typescript](https://typescriptlang.org), but can be called from either Javascript or Typescript. @@ -16,6 +15,7 @@ There are future plans to also build a jQuery compatible library but for now, all of the examples and instructions assume the node client. # Installation + ```console npm install @kubernetes/client-node ``` @@ -23,22 +23,22 @@ npm install @kubernetes/client-node # Example code ## List all pods + ```javascript const k8s = require('@kubernetes/client-node'); - const kc = new k8s.KubeConfig(); kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.Core_v1Api); -k8sApi.listNamespacedPod('default') - .then((res) => { - console.log(res.body); - }); +k8sApi.listNamespacedPod('default').then((res) => { + console.log(res.body); +}); ``` ## Create a new namespace + ```javascript const k8s = require('@kubernetes/client-node'); @@ -48,29 +48,28 @@ kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.Core_v1Api); var namespace = { - metadata: { - name: 'test' - } + metadata: { + name: 'test', + }, }; k8sApi.createNamespace(namespace).then( - (response) => { - console.log('Created namespace'); - console.log(response); - k8sApi.readNamespace(namespace.metadata.name).then( - (response) => { + (response) => { + console.log('Created namespace'); console.log(response); - k8sApi.deleteNamespace( - namespace.metadata.name, {} /* delete options */); - }); - }, - (err) => { - console.log('Error!: ' + err); - } + k8sApi.readNamespace(namespace.metadata.name).then((response) => { + console.log(response); + k8sApi.deleteNamespace(namespace.metadata.name, {} /* delete options */); + }); + }, + (err) => { + console.log('Error!: ' + err); + }, ); ``` # Additional Examples + There are several more examples in the [examples](https://github.com/kubernetes-client/javascript/tree/master/examples) directory. # Development @@ -92,6 +91,14 @@ cd javascript ../gen/openapi/typescript.sh src settings ``` +## Formatting + +Run `npm run format` or install an editor plugin like https://github.com/prettier/prettier-vscode. + +## Linting + +Run `npm run lint` or install an editor plugin like https://github.com/Microsoft/vscode-typescript-tslint-plugin + # Testing Tests are written using the [Chai](http://chaijs.com/) library. See