mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-02-14 18:29:53 +00:00
Merge pull request #71 from replicatedhq/divolgin/output-names
support multiple containers in pod logs
This commit is contained in:
@@ -179,18 +179,21 @@ func runCollectors(v *viper.Viper, collector troubleshootv1beta1.Collector, prog
|
||||
continue
|
||||
}
|
||||
|
||||
collectorDir, err := parseAndSaveCollectorOutput(string(result), bundlePath)
|
||||
newCollectorDirs, err := parseAndSaveCollectorOutput(string(result), bundlePath)
|
||||
if err != nil {
|
||||
progressChan <- fmt.Errorf("failed to parse collector spec %q: %v", collector.GetDisplayName(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
if collectorDir == "" {
|
||||
if len(newCollectorDirs) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
progressChan <- collectorDir
|
||||
collectorDirs = append(collectorDirs, collectorDir)
|
||||
// TODO: better progress....
|
||||
for _, d := range newCollectorDirs {
|
||||
progressChan <- d
|
||||
}
|
||||
collectorDirs = append(collectorDirs, newCollectorDirs...)
|
||||
}
|
||||
|
||||
tarGz := archiver.TarGz{
|
||||
@@ -219,53 +222,58 @@ func runCollectors(v *viper.Viper, collector troubleshootv1beta1.Collector, prog
|
||||
return filename, nil
|
||||
}
|
||||
|
||||
func parseAndSaveCollectorOutput(output string, bundlePath string) (string, error) {
|
||||
dir := ""
|
||||
func parseAndSaveCollectorOutput(output string, bundlePath string) ([]string, error) {
|
||||
rootDirs := make(map[string]bool)
|
||||
|
||||
input := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(output), &input); err != nil {
|
||||
return "", errors.Wrap(err, "unmarshal output")
|
||||
return nil, errors.Wrap(err, "unmarshal output")
|
||||
}
|
||||
|
||||
for filename, maybeContents := range input {
|
||||
fileDir, fileName := filepath.Split(filename)
|
||||
outPath := filepath.Join(bundlePath, fileDir)
|
||||
dir = outPath
|
||||
rootDirs[outPath] = true
|
||||
|
||||
if err := os.MkdirAll(outPath, 0777); err != nil {
|
||||
return "", errors.Wrap(err, "create output file")
|
||||
return nil, errors.Wrap(err, "create output file")
|
||||
}
|
||||
|
||||
switch maybeContents.(type) {
|
||||
case string:
|
||||
decoded, err := base64.StdEncoding.DecodeString(maybeContents.(string))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "decode collector output")
|
||||
return nil, errors.Wrap(err, "decode collector output")
|
||||
}
|
||||
|
||||
if err := writeFile(filepath.Join(outPath, fileName), decoded); err != nil {
|
||||
return "", errors.Wrap(err, "write collector output")
|
||||
return nil, errors.Wrap(err, "write collector output")
|
||||
}
|
||||
|
||||
case map[string]interface{}:
|
||||
for k, v := range maybeContents.(map[string]interface{}) {
|
||||
s, _ := filepath.Split(filepath.Join(outPath, fileName, k))
|
||||
if err := os.MkdirAll(s, 0777); err != nil {
|
||||
return "", errors.Wrap(err, "write output directories")
|
||||
return nil, errors.Wrap(err, "write output directories")
|
||||
}
|
||||
|
||||
decoded, err := base64.StdEncoding.DecodeString(v.(string))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "decode output")
|
||||
return nil, errors.Wrap(err, "decode output")
|
||||
}
|
||||
if err := writeFile(filepath.Join(outPath, fileName, k), decoded); err != nil {
|
||||
return "", errors.Wrap(err, "write output")
|
||||
return nil, errors.Wrap(err, "write output")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dir, nil
|
||||
dirs := make([]string, 0)
|
||||
for dir := range rootDirs {
|
||||
dirs = append(dirs, dir)
|
||||
}
|
||||
|
||||
return dirs, nil
|
||||
}
|
||||
|
||||
func uploadSupportBundle(r *troubleshootv1beta1.ResultRequest, archivePath string) error {
|
||||
|
||||
@@ -27,6 +27,7 @@ type Logs struct {
|
||||
CollectorMeta `json:",inline" yaml:",inline"`
|
||||
Selector []string `json:"selector" yaml:"selector"`
|
||||
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||
Containers []string `json:"containers,omitempty" yaml:"containers,omitempty"`
|
||||
Limits *LogLimits `json:"limits,omitempty" yaml:"omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -882,6 +882,11 @@ func (in *Logs) DeepCopyInto(out *Logs) {
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Containers != nil {
|
||||
in, out := &in.Containers, &out.Containers
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Limits != nil {
|
||||
in, out := &in.Limits, &out.Limits
|
||||
*out = new(LogLimits)
|
||||
|
||||
@@ -42,18 +42,34 @@ func Logs(ctx *Context, logsCollector *troubleshootv1beta1.Logs) ([]byte, error)
|
||||
|
||||
if len(pods) > 0 {
|
||||
for _, pod := range pods {
|
||||
podLogs, err := getPodLogs(client, pod, logsCollector.Limits, false)
|
||||
if err != nil {
|
||||
key := fmt.Sprintf("%s/%s-errors.json", pod.Namespace, pod.Name)
|
||||
logsOutput.Errors[key], err = marshalNonNil([]string{err.Error()})
|
||||
if len(logsCollector.Containers) == 0 {
|
||||
podLogs, err := getPodLogs(client, pod, "", logsCollector.Limits, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
key := fmt.Sprintf("%s/%s-errors.json", pod.Namespace, pod.Name)
|
||||
logsOutput.Errors[key], err = marshalNonNil([]string{err.Error()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
for k, v := range podLogs {
|
||||
logsOutput.PodLogs[k] = v
|
||||
}
|
||||
} else {
|
||||
for _, container := range logsCollector.Containers {
|
||||
containerLogs, err := getPodLogs(client, pod, container, logsCollector.Limits, false)
|
||||
if err != nil {
|
||||
key := fmt.Sprintf("%s/%s/%s-errors.json", pod.Namespace, pod.Name, container)
|
||||
logsOutput.Errors[key], err = marshalNonNil([]string{err.Error()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
for k, v := range containerLogs {
|
||||
logsOutput.PodLogs[k] = v
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
for k, v := range podLogs {
|
||||
logsOutput.PodLogs[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +104,10 @@ func listPodsInSelectors(client *kubernetes.Clientset, namespace string, selecto
|
||||
return pods.Items, nil
|
||||
}
|
||||
|
||||
func getPodLogs(client *kubernetes.Clientset, pod corev1.Pod, limits *troubleshootv1beta1.LogLimits, follow bool) (map[string][]byte, error) {
|
||||
func getPodLogs(client *kubernetes.Clientset, pod corev1.Pod, container string, limits *troubleshootv1beta1.LogLimits, follow bool) (map[string][]byte, error) {
|
||||
podLogOpts := corev1.PodLogOptions{
|
||||
Follow: follow,
|
||||
Follow: follow,
|
||||
Container: container,
|
||||
}
|
||||
|
||||
defaultMaxLines := int64(10000)
|
||||
@@ -126,8 +143,13 @@ func getPodLogs(client *kubernetes.Clientset, pod corev1.Pod, limits *troublesho
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fileKey := fmt.Sprintf("%s/%s.txt", pod.Namespace, pod.Name)
|
||||
if container != "" {
|
||||
fileKey = fmt.Sprintf("%s/%s/%s.txt", pod.Namespace, pod.Name, container)
|
||||
}
|
||||
|
||||
return map[string][]byte{
|
||||
fmt.Sprintf("%s/%s.txt", pod.Namespace, pod.Name): buf.Bytes(),
|
||||
fileKey: buf.Bytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ func runWithoutTimeout(ctx *Context, pod *corev1.Pod, runCollector *troubleshoot
|
||||
limits := troubleshootv1beta1.LogLimits{
|
||||
MaxLines: 10000,
|
||||
}
|
||||
podLogs, err := getPodLogs(client, *pod, &limits, true)
|
||||
podLogs, err := getPodLogs(client, *pod, "", &limits, true)
|
||||
|
||||
for k, v := range podLogs {
|
||||
runOutput.PodLogs[k] = v
|
||||
|
||||
Reference in New Issue
Block a user