-
Notifications
You must be signed in to change notification settings - Fork 557
Add support for the v5 protocol #2037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,6 +2,7 @@ import { promisify } from 'util'; | |||||
import { expect } from 'chai'; | ||||||
import WebSocket = require('isomorphic-ws'); | ||||||
import { ReadableStreamBuffer, WritableStreamBuffer } from 'stream-buffers'; | ||||||
import stream = require('stream'); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||||||
|
||||||
import { V1Status } from './api'; | ||||||
import { KubeConfig } from './config'; | ||||||
|
@@ -119,7 +120,7 @@ describe('WebSocket', () => { | |||||
|
||||||
const handler = new WebSocketHandler( | ||||||
kc, | ||||||
(uri: string, opts: WebSocket.ClientOptions): WebSocket.WebSocket => { | ||||||
(uri: string, protocols: string[], opts: WebSocket.ClientOptions): WebSocket.WebSocket => { | ||||||
uriOut = uri; | ||||||
return mockWs as WebSocket.WebSocket; | ||||||
}, | ||||||
|
@@ -170,7 +171,7 @@ describe('WebSocket', () => { | |||||
|
||||||
const handler = new WebSocketHandler( | ||||||
kc, | ||||||
(uri: string, opts: WebSocket.ClientOptions): WebSocket.WebSocket => { | ||||||
(uri: string, protocols: string[], opts: WebSocket.ClientOptions): WebSocket.WebSocket => { | ||||||
uriOut = uri; | ||||||
return mockWs as WebSocket.WebSocket; | ||||||
}, | ||||||
|
@@ -239,7 +240,7 @@ describe('WebSocket', () => { | |||||
|
||||||
const handler = new WebSocketHandler( | ||||||
kc, | ||||||
(uri: string, opts: WebSocket.ClientOptions): WebSocket.WebSocket => { | ||||||
(uri: string, protocols: string[], opts: WebSocket.ClientOptions): WebSocket.WebSocket => { | ||||||
uriOut = uri; | ||||||
return mockWs as WebSocket.WebSocket; | ||||||
}, | ||||||
|
@@ -303,6 +304,107 @@ describe('WebSocket', () => { | |||||
}); | ||||||
}); | ||||||
|
||||||
describe('V5 protocol support', () => { | ||||||
it('should handle close', async () => { | ||||||
const kc = new KubeConfig(); | ||||||
const host = 'foo.company.com'; | ||||||
const server = `https://${host}`; | ||||||
kc.clusters = [ | ||||||
{ | ||||||
name: 'cluster', | ||||||
server, | ||||||
} as Cluster, | ||||||
] as Cluster[]; | ||||||
kc.contexts = [ | ||||||
{ | ||||||
cluster: 'cluster', | ||||||
user: 'user', | ||||||
} as Context, | ||||||
] as Context[]; | ||||||
kc.users = [ | ||||||
{ | ||||||
name: 'user', | ||||||
} as User, | ||||||
]; | ||||||
|
||||||
const mockWs = { | ||||||
protocol: 'v5.channel.k8s.io', | ||||||
} as WebSocket.WebSocket; | ||||||
let uriOut = ''; | ||||||
let endCalled = false; | ||||||
const handler = new WebSocketHandler( | ||||||
kc, | ||||||
(uri: string, protocols: string[], opts: WebSocket.ClientOptions): WebSocket.WebSocket => { | ||||||
uriOut = uri; | ||||||
return mockWs as WebSocket.WebSocket; | ||||||
}, | ||||||
{ | ||||||
stdin: process.stdin, | ||||||
stderr: process.stderr, | ||||||
stdout: { | ||||||
end: () => { | ||||||
endCalled = true; | ||||||
}, | ||||||
} as stream.Writable, | ||||||
}, | ||||||
); | ||||||
const path = '/some/path'; | ||||||
|
||||||
const promise = handler.connect(path, null, null); | ||||||
await setImmediatePromise(); | ||||||
|
||||||
expect(uriOut).to.equal(`wss://${host}${path}`); | ||||||
|
||||||
const event = { | ||||||
target: mockWs, | ||||||
type: 'open', | ||||||
}; | ||||||
mockWs.onopen!(event); | ||||||
const errEvt = { | ||||||
error: {}, | ||||||
message: 'some message', | ||||||
type: 'some type', | ||||||
target: mockWs, | ||||||
}; | ||||||
const closeBuff = Buffer.alloc(2); | ||||||
closeBuff.writeUint8(255, 0); | ||||||
closeBuff.writeUint8(WebSocketHandler.StdoutStream, 1); | ||||||
|
||||||
mockWs.onmessage!({ | ||||||
data: closeBuff, | ||||||
type: 'type', | ||||||
target: mockWs, | ||||||
}); | ||||||
await promise; | ||||||
expect(endCalled).to.be.true; | ||||||
}); | ||||||
it('should handle closing stdin < v4 protocol', () => { | ||||||
const ws = { | ||||||
// send is not defined, so this will throw if we try to send the close message. | ||||||
close: () => {}, | ||||||
} as WebSocket; | ||||||
const stdinStream = new ReadableStreamBuffer(); | ||||||
WebSocketHandler.handleStandardInput(ws, stdinStream); | ||||||
stdinStream.emit('end'); | ||||||
}); | ||||||
it('should handle closing stdin v5 protocol', () => { | ||||||
let sent: Buffer | null = null; | ||||||
const ws = { | ||||||
protocol: 'v5.channel.k8s.io', | ||||||
send: (data) => { | ||||||
sent = data; | ||||||
}, | ||||||
close: () => {}, | ||||||
} as WebSocket; | ||||||
const stdinStream = new ReadableStreamBuffer(); | ||||||
WebSocketHandler.handleStandardInput(ws, stdinStream); | ||||||
stdinStream.emit('end'); | ||||||
expect(sent).to.not.be.null; | ||||||
expect(sent!.readUint8(0)).to.equal(255); // CLOSE signal | ||||||
expect(sent!.readUInt8(1)).to.equal(0); // Stdin stream is #0 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason one of these uses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Converted all to readUint8 The Internet seems to be ambiguous on which is the right casing. Both appear to work... |
||||||
}); | ||||||
}); | ||||||
|
||||||
describe('Restartable Handle Standard Input', () => { | ||||||
it('should throw on negative retry', () => { | ||||||
const p = new Promise<WebSocket.WebSocket>(() => {}); | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are three
console.log()
s left over.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ugh, so embarrassing to leave test printfs in the PR :)
fixed.