Merge pull request #71 from replicatedhq/divolgin/output-names

support multiple containers in pod logs
This commit is contained in:
divolgin
2019-10-24 11:31:45 -07:00
committed by GitHub
5 changed files with 65 additions and 29 deletions

View File

@@ -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 {

View File

@@ -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"`
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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