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
Copy collector enhanced #237
Copy collector enhanced #237
Conversation
@manavellamnimble this should use |
@divolgin what should we do in the event hat |
@divolgin @marccampbell those are both good points. I can figure out a way to test if tar is installed (checking if running I assume we are not considering windows-based containers, is that correct? Let me know what you think! |
@marccampbell it is possible for tar to not installed. But I'd argue that this is such a rare configuration that we can resolve it with documentation. Even alpine image comes with tar. |
Ok, I am working on a solution using tar too, and making only one call to k8s client, I hope to have it working by tomorrow, and then you can tell me which of the two solutions would you rather implement. Does that sounds ok? |
I would recommend "borrowing" from this code |
@marccampbell @divolgin @emosbaugh I was able to extract the folder or files as .tar and place the tar file inside the support bundle under /<pod.name>/<filename.tar>. Nevertheless, it doesn't work when the folder being copied contains an image. I tracked the problem to the redactor (If I skip the redaction stage, everything works ok). My question is, should I work in finding way to preserve images? Or are images not important and I can exclude them from the tar? |
There is a known issue that redaction appends new lines. I wonder if this is the issue with images? |
@emosbaugh It might be, yes! But you made me realize, it is not posible to redact any file in a tar file. Based on what you say, the redactor must be making a modification in the bytes of the tar file, corrupting the file. I think...maybe extracting the files in the tar prior to redaction may work and have a double benefit. We only make one request to the client, and we can apply the redactors to the files, which may solve issue #58 too. |
@laverya you may have more of an opinion on the last comment from @manavellamnimble |
I think the redactors should be taking archives into account. If a tar or zip or tgz is found in a bundle, the Redactor phase must decompress, redact and recommpress. |
pkg/collect/copy.go
Outdated
copyCollector.ContainerPath: output.Bytes(), | ||
}, nil | ||
for _, file := range filepaths { | ||
if file != "" { |
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.
This would be better written has
if file == "" {
continue
}
The code is less conditionally indented and more readable this way
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.
@CodeLingoBot capture continue in conditional in loop
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.
Rule captured at https://dash.codelingo.io/repos/replicatedhq/troubleshoot/rules/1392
CodeLingoBot Help
When responding to PR-level comments, I understand the following commands:
-
capture
to capture the context for a fresh rule. -
review
to trigger a fresh review.
When responding to comments on specific lines of code, I understand the following commands:
-
capture
to capture the context for a fresh rule. -
review
to trigger a fresh review. -
ignore
to ignore the parent review comment. -
unignore
to stop ignoring a parent review comment.
pkg/collect/copy.go
Outdated
if file != "" { | ||
command := []string{"cat", file} | ||
|
||
req := client.CoreV1().RESTClient().Post().Resource("pods").Name(pod.Name).Namespace(pod.Namespace).SubResource("exec") |
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.
This is unnecessarily verbose.
req := client.Corev1().Pods(pod.Namespace).Get(pod.Name)
Is cleaner and how we use the clientset
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.
@CodeLingoBot capture unnecessary use of client-go restClient
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.
Rule captured at https://dash.codelingo.io/repos/replicatedhq/troubleshoot/rules/1393
CodeLingoBot Help
When responding to PR-level comments, I understand the following commands:
-
capture
to capture the context for a fresh rule. -
review
to trigger a fresh review.
When responding to comments on specific lines of code, I understand the following commands:
-
capture
to capture the context for a fresh rule. -
review
to trigger a fresh review. -
ignore
to ignore the parent review comment. -
unignore
to stop ignoring a parent review comment.
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.
Hi Marc! I didn't have much contact with the client set yet, so I left that line as it was. The way you suggest returns another type of variable and requires another type of variable too instead of pod.Name. I didn't investigate it further because I am sure I will have to deal with the clientset in later PR's, and I didn't wanted to delay the copy collector.
That said I can either change it later, once I've dealt with the client set, or look into it now, as you prefer!
@marccampbell Good Morning Marc! You are right, it is way better as you propose in both cases, thank you for the observation! I will work in the following process for the copy collector (@divolgin and @emosbaugh I think your opinion about the process would be helpful too): 1- Compress file or folder in the pod and copy it (1 request to the client to get all, already working) Considering that originally the copy collector used cat to copy a file, I would think this would be a great improvement. Let me know what you think! |
that looks good. would you include gzipped files as well? |
Yes, I was thinking about choosing a decompressor/compresor according to the extension of the compressed file in the folder. |
@manavellamnimble I think it's not necessary to re-compress everything. If fact, it's probably better to leave the result as a folder structure matching the original folder in the pod. |
@divolgin taking into account what you said about keeping the file info of the copied files (for example, permissions), I found that the best way to keep this info was to make a tar file. In the image, for example, I copied two folders (httpd and httpdocs) and one file (cheddar.yaml). And every file inside each tar is redacted (and also each file inside a tar inside the tar...tar-inception). Of course it may be removed but I think it is a robust solution! First thing tomorrow I will commit and we can discuss the code! Let me know what you think! |
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.
LGTM.
@marccampbell @divolgin @emosbaugh Morning! I've made a new commit. The upgrades are:
Possible upgrades:
Please let me know any thought you have! Have a great day! As an example, the image represents the output of the following yaml file:
|
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.
LGTM.
tar.gz and .tgz included
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.
LGTM.
@divolgin @emosbaugh Hi there! I've added the possibility to decompress and redact files from .tar.gz and .tgz files. It works on nested tar-ish files as well. I tried to use the same functions, to keep it simple. |
tar.gz and .tgz included
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.
LGTM.
tar.gz and .tgz included
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.
LGTM.
@manavellamnimble does this copy collector leave folders as folders in the support bundle, or are they in tar format? |
@divolgin The target folder (lets say, folder httpd in go/src/app/httpd) is place as tar in the bundle under /<pod_name>/ go/src/app/htrpd.tar as tar. Every content in the tar is left as it was (folders as folders, files as files and compressed files (tar, tar.gz and tgz) as compressed files). |
pkg/collect/redact.go
Outdated
var err error | ||
if filepath.Ext(filename) != ".tar" { | ||
zr, err = gzip.NewReader(tarFile) | ||
defer zr.Close() |
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.
this defer should come after checking the err != nil
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.
Yep, you are right! Done
tar.gz and .tgz included
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.
LGTM.
@manavellamnimble files and folders in the support bundle should match the source. So in your example, |
Copy into folder
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.
LGTM.
Copy into folder
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.
LGTM.
@divolgin Hi Dimitriy! After considering many approaches, I think this is the cleaner one. It requires almost no modifications, and it doesnt spread changes through the application. It stores folders and files in the support bundle, keeping the permissions and matching the path in origin. It maintains all the upgrades developed until this point. I've tested it copying two folders (httpd and htdocs) and a file (k8s/ingress.yaml), see image below: |
cmd/troubleshoot/cli/run.go
Outdated
for filename, maybeContents := range output { | ||
if strings.Contains(c.GetDisplayName(), "copy") { |
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.
I think this should be if c.Collect.Copy != nil {
command modified
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.
LGTM.
@divolgin Hi Dimitriy, good news... I end up changing the command. Working with the client set today I realized that stdout is redirected when called from the client, therefore avoiding the error "refusing to write...". I've tested it and it works. I've also changed the conditional you suggested. |
Hi there! To copy all the files in a given directory, I added this three steps:
find <folder or file path specified> -type f
in the container console, which finds all the files and returns each pathI've already tested it with different pods, and with multiple copy statements in the yaml file referencing different containers. Files are stored as before, under namespace/pod.name/containerpath// filename in the support-bundle.
Let me know if there is something you would like to edit/add!
Fix #212