Skip to content
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

Fixes #82 Add a client for the pod read-log endpoint #83

Merged
merged 1 commit into from
Mar 27, 2019

Conversation

dbolkensteyn
Copy link
Contributor

@dbolkensteyn dbolkensteyn commented Aug 15, 2018

This PR adds the ability to read the logs of a pod. Fixes #82

@k8s-ci-robot k8s-ci-robot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Aug 15, 2018
@k8s-ci-robot
Copy link
Contributor

Thanks for your pull request. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please follow instructions at https://git.k8s.io/community/CLA.md#the-contributor-license-agreement to sign the CLA.

It may take a couple minutes for the CLA signature to be fully registered; after that, please reply here with a new comment and we'll verify. Thanks.


Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. label Aug 15, 2018
@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. and removed cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. labels Aug 15, 2018
@@ -87,7 +88,7 @@ export class WebSocketHandler {
textHandler(message.utf8Data);
}
} else if (message.type === 'binary') {
if (binaryHandler) {
if (binaryHandler && message.binaryData.length > 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On my Kubernetes cluster, the first message received is an empty one.

const promise = this.handler.connect(path, null, (streamNum: number, buff: Buffer) => {
const charBuff = Buffer.allocUnsafe(1)
charBuff.writeInt8(streamNum, 0)
stream.write(Buffer.concat([charBuff, buff]));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Little bit ugly trick, but this allows to re-use the code from WebSocketHandler without having to it in a way that could break the other consumers of it (Attach, Exec).

A single write() call is issued on the stream because that tends to correspond to a line in the logs (although this is probably not guaranteed).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry can you explain why this is needed? This is probably a bug in WebSocketHandler that should be fixed instead of doing this here...

(and it's probably my bug :)

@dbolkensteyn dbolkensteyn force-pushed the read-log branch 3 times, most recently from 47d5225 to 4e8676c Compare August 15, 2018 20:32
@dbolkensteyn
Copy link
Contributor Author

dbolkensteyn commented Aug 16, 2018

There is a flaky error while reading the logs:

internal/buffer.js:35
    throw new ERR_OUT_OF_RANGE('value', `>= ${min} and <= ${max}`, value);
    ^

RangeError [ERR_OUT_OF_RANGE]: The value of "value" is out of range. It must be >= 0 and <= 4294967295. Received -2003205171
    at checkInt (internal/buffer.js:35:11)
    at writeU_Int32BE (internal/buffer.js:625:3)
    at Buffer.writeUInt32BE (internal/buffer.js:638:10)
    at WebSocketFrame.toBuffer (/Users/dinesh/Desktop/projects/javascript/node-client/node_modules/websocket/lib/WebSocketFrame.js:257:24)

This is already fixed upstream in this commit theturtle32/WebSocket-Node@12ed73d

All we need is to update to the latest release 1.0.26, which indeed solves this problem.

@@ -38,7 +38,7 @@
"request": "^2.72.0",
"shelljs": "^0.7.8 ",
"underscore": "^1.8.3",
"websocket": "^1.0.25"
"websocket": "^1.0.26"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The diff on the auto-generated package-lock.json is pretty huge, unsure what to do with that, so I'm excluding it for the time being from this PR

}

// TODO add support for limitBytes, previous, sinceSeconds and tailLines
public log(namespace: string, podName: string, containerName: string,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation is weird here, can you run this through tslint?

public 'handler': WebSocketHandler;

public constructor(config: KubeConfig) {
this.handler = new WebSocketHandler(config);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the log endpoint even use WebSockets? I thought it was a standard hanging GET, that's what we do in Java:

https://github.com/kubernetes-client/java/blob/master/util/src/main/java/io/kubernetes/client/PodLogs.java#L65

@brendandburns
Copy link
Contributor

Thanks for the PR!

Do we really need WebSockets here? I think in other clients this is implemented as a straight GET...

Thanks!

@brendandburns
Copy link
Contributor

@dbolkensteyn friendly ping on this, I'd love to get it merged, but I have some thoughts.

Thanks!

@dbolkensteyn
Copy link
Contributor Author

And I thank you for the valuable feedback @brendandburns - I'll come back to this during the week.

@brendandburns
Copy link
Contributor

Friendly ping on this if you still have time I'd love to get this merged.

Thanks!

@brendandburns
Copy link
Contributor

@dbolkensteyn Friendly ping on this.

Thanks!

@brendandburns
Copy link
Contributor

Final ping, otherwise I'm going to close and build a different implementation of this functionality.

Thanks!

@dbolkensteyn dbolkensteyn force-pushed the read-log branch 2 times, most recently from 428bff4 to a649a15 Compare March 19, 2019 23:24
@dbolkensteyn
Copy link
Contributor Author

dbolkensteyn commented Mar 19, 2019

Sorry for the late follow-up @brendandburns , I've just forced-pushed a new implementation that incorporates all of your feedback and the one from #214 which actually implements the same feature (but hard-codes follow to true)

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Mar 19, 2019
@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Mar 20, 2019
}
}).on('response', (response) => {
if (response.statusCode === 200) {
req.pipe(stream);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unlike #214 this will only start to pipe the "logs" when a 200 response is returned (else Kubernetes error jsons might get treated as logs)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbolkensteyn How to stop piping? I am successfully able to open the logs (follow option) but what is the right way to terminate underlying request?

public log(
namespace: string,
podName: string,
containerName: string,
Copy link
Contributor Author

@dbolkensteyn dbolkensteyn Mar 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

containerName is mandatory

/**
* Follow the log stream of the pod. Defaults to false.
*/
follow?: boolean;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow is taken as a parameter and not hard-coded


import { KubeConfig } from './config';

export interface LogOptions {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is taken over from #214 as it seems as a nice way to avoid overly-parameterized methods

@brendandburns
Copy link
Contributor

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 27, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: brendandburns, dbolkensteyn

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 27, 2019
@k8s-ci-robot k8s-ci-robot merged commit 4a5b84d into kubernetes-client:master Mar 27, 2019
@abierbaum
Copy link

Does anyone have an example of using this code? I tried to use it to stream logs but have not gotten it to work.

@izhilenkov
Copy link

@abierbaum You could use something like LineStream from byline (which exactly Transform) as a line stream for quick example

import { KubeConfig, Log } from '@kubernetes/client-node';
import { LineStream } from 'byline';

const kc = new KubeConfig();
kc.loadFromDefault();

const log = new Log(kc);
const logStream = new LineStream();

logStream.on('data', data => console.log(data.toString()));

log.log(namespace, pod, container, logStream, (err) => console.log(err), { follow: true });

@kingdevnl
Copy link

How could i close the log?

Iv'e tried to call logStream.destroy() but the program still keeps running.

@Celthi
Copy link

Celthi commented Mar 25, 2021

Hi guys, I use this class with follow=true but my file only has part of the log instead of all the log from the pod?
Is there anything I need to pay attention to use this class?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a client for the pod read-log endpoint
8 participants