Skip to content

Commit

Permalink
Pod logs
Browse files Browse the repository at this point in the history
  • Loading branch information
marccampbell committed Jul 18, 2019
1 parent 58d088b commit 270ccc0
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 8 deletions.
19 changes: 19 additions & 0 deletions config/crds/troubleshoot.replicated.com_collectors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,25 @@ spec:
type: object
clusterResources:
type: object
logs:
properties:
limits:
properties:
maxAge:
type: string
maxLines:
format: int64
type: integer
type: object
namespace:
type: string
selector:
items:
type: string
type: array
required:
- selector
type: object
secret:
properties:
includeValue:
Expand Down
19 changes: 19 additions & 0 deletions config/crds/troubleshoot.replicated.com_preflights.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,25 @@ spec:
type: object
clusterResources:
type: object
logs:
properties:
limits:
properties:
maxAge:
type: string
maxLines:
format: int64
type: integer
type: object
namespace:
type: string
selector:
items:
type: string
type: array
required:
- selector
type: object
secret:
properties:
includeValue:
Expand Down
45 changes: 45 additions & 0 deletions config/crds/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ func (in *Collect) DeepCopyInto(out *Collect) {
*out = new(Secret)
**out = **in
}
if in.Logs != nil {
in, out := &in.Logs, &out.Logs
*out = new(Logs)
(*in).DeepCopyInto(*out)
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Collect.
Expand Down Expand Up @@ -613,6 +618,46 @@ func (in *Ingress) DeepCopy() *Ingress {
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LogLimits) DeepCopyInto(out *LogLimits) {
*out = *in
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogLimits.
func (in *LogLimits) DeepCopy() *LogLimits {
if in == nil {
return nil
}
out := new(LogLimits)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Logs) DeepCopyInto(out *Logs) {
*out = *in
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Limits != nil {
in, out := &in.Limits, &out.Limits
*out = new(LogLimits)
**out = **in
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Logs.
func (in *Logs) DeepCopy() *Logs {
if in == nil {
return nil
}
out := new(Logs)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Outcome) DeepCopyInto(out *Outcome) {
*out = *in
Expand Down
13 changes: 10 additions & 3 deletions config/samples/troubleshoot_v1beta1_collector.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ metadata:
spec:
# - clusterInfo: {}
# - clusterResources: {}
- secret:
name: illmannered-cricket-mysql
# - secret:
# name: illmannered-cricket-mysql
# namespace: default
# key: mysql-password
- logs:
selector:
- name=nginx-ingress-microk8s
namespace: default
key: mysql-password
limits:
maxAge: 30d
maxLines: 10000
12 changes: 12 additions & 0 deletions pkg/apis/troubleshoot/v1beta1/collector_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,20 @@ type Secret struct {
IncludeValue bool `json:"includeValue,omitempty" yaml:"includeValue,omitempty"`
}

type LogLimits struct {
MaxAge string `json:"maxAge,omitempty" yaml:"maxAge,omitempty"`
MaxLines int64 `json:"maxLines,omitempty" yaml:"maxLines,omitempty"`
}

type Logs struct {
Selector []string `json:"selector" yaml:"selector"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Limits *LogLimits `json:"limits,omitempty" yaml:"omitempty"`
}

type Collect struct {
ClusterInfo *ClusterInfo `json:"clusterInfo,omitempty" yaml:"clusterInfo,omitempty"`
ClusterResources *ClusterResources `json:"clusterResources,omitempty" yaml:"clusterResources,omitempty"`
Secret *Secret `json:"secret,omitempty" yaml:"secret,omitempty"`
Logs *Logs `json:"logs,omitempty" yaml:"logs,omitempty"`
}
45 changes: 45 additions & 0 deletions pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,11 @@ func (in *Collect) DeepCopyInto(out *Collect) {
*out = new(Secret)
**out = **in
}
if in.Logs != nil {
in, out := &in.Logs, &out.Logs
*out = new(Logs)
(*in).DeepCopyInto(*out)
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Collect.
Expand Down Expand Up @@ -629,6 +634,46 @@ func (in *Ingress) DeepCopy() *Ingress {
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LogLimits) DeepCopyInto(out *LogLimits) {
*out = *in
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogLimits.
func (in *LogLimits) DeepCopy() *LogLimits {
if in == nil {
return nil
}
out := new(LogLimits)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Logs) DeepCopyInto(out *Logs) {
*out = *in
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Limits != nil {
in, out := &in.Limits, &out.Limits
*out = new(LogLimits)
**out = **in
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Logs.
func (in *Logs) DeepCopy() *Logs {
if in == nil {
return nil
}
out := new(Logs)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Outcome) DeepCopyInto(out *Outcome) {
*out = *in
Expand Down
3 changes: 3 additions & 0 deletions pkg/collect/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func (c *Collector) RunCollectorSync() error {
if collect.Secret != nil {
return Secret(collect.Secret)
}
if collect.Logs != nil {
return Logs(collect.Logs)
}

return errors.New("no spec found to run")
}
Expand Down
116 changes: 116 additions & 0 deletions pkg/collect/logs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package collect

import (
"bytes"
"encoding/json"
"fmt"
"io"
"strings"
"time"

troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)

type LogsOutput struct {
PodLogs map[string][]byte `json:"logs/,omitempty"`
}

func Logs(logsCollector *troubleshootv1beta1.Logs) error {
cfg, err := config.GetConfig()
if err != nil {
return err
}

client, err := kubernetes.NewForConfig(cfg)
if err != nil {
return err
}

pods, err := listPodsInSelectors(client, logsCollector.Namespace, logsCollector.Selector)
if err != nil {
return err
}

logsOutput := LogsOutput{
PodLogs: make(map[string][]byte),
}
for _, pod := range pods {
podLogs, err := getPodLogs(client, pod, logsCollector.Limits)
if err != nil {
return err
}

for k, v := range podLogs {
logsOutput.PodLogs[k] = v
}
}

b, err := json.MarshalIndent(logsOutput, "", " ")
if err != nil {
return err
}

fmt.Printf("%s\n", b)

return nil
}

func listPodsInSelectors(client *kubernetes.Clientset, namespace string, selector []string) ([]corev1.Pod, error) {
serializedLabelSelector := strings.Join(selector, ",")

listOptions := metav1.ListOptions{
LabelSelector: serializedLabelSelector,
}

pods, err := client.CoreV1().Pods(namespace).List(listOptions)
if err != nil {
return nil, err
}

return pods.Items, nil
}

func getPodLogs(client *kubernetes.Clientset, pod corev1.Pod, limits *troubleshootv1beta1.LogLimits) (map[string][]byte, error) {
podLogOpts := corev1.PodLogOptions{}

defaultMaxLines := int64(10000)
if limits == nil || limits.MaxLines == 0 {
podLogOpts.TailLines = &defaultMaxLines
} else {
podLogOpts.TailLines = &limits.MaxLines
}

if limits != nil && limits.MaxAge != "" {
parsedDuration, err := time.ParseDuration(limits.MaxAge)
if err != nil {
fmt.Printf("unable to parse time duration %s\n", limits.MaxAge)
} else {
now := time.Now()
then := now.Add(0 - parsedDuration)
kthen := metav1.NewTime(then)

podLogOpts.SinceTime = &kthen
}
}

req := client.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &podLogOpts)
podLogs, err := req.Stream()
if err != nil {
return nil, err
}
defer podLogs.Close()

buf := new(bytes.Buffer)
_, err = io.Copy(buf, podLogs)
if err != nil {
return nil, err
}

return map[string][]byte{
fmt.Sprintf("%s/%s.txt", pod.Namespace, pod.Name): buf.Bytes(),
}, nil
}
4 changes: 4 additions & 0 deletions pkg/collect/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,9 @@ func idForCollector(collector *troubleshootv1beta1.Collect) string {
if collector.Secret != nil {
return fmt.Sprintf("secret-%s%s", collector.Secret.Namespace, collector.Secret.Name)
}
if collector.Logs != nil {
randomString := "abcdef" // TODO
return fmt.Sprintf("logs-%s%s", collector.Logs.Namespace, randomString)
}
return ""
}
11 changes: 8 additions & 3 deletions pkg/controller/collectorjob/collectorjob_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,12 +433,17 @@ func (r *ReconcileCollectorJob) createCollectorPod(instance *troubleshootv1beta1
func idForCollector(collector *troubleshootv1beta1.Collect) string {
if collector.ClusterInfo != nil {
return "cluster-info"
} else if collector.ClusterResources != nil {
}
if collector.ClusterResources != nil {
return "cluster-resources"
} else if collector.Secret != nil {
}
if collector.Secret != nil {
return fmt.Sprintf("secret-%s%s", collector.Secret.Namespace, collector.Secret.Name)
}

if collector.Logs != nil {
randomString := "abcdef" // TODO
return fmt.Sprintf("logs-%s%s", collector.Logs.Namespace, randomString)
}
return ""
}

Expand Down
10 changes: 8 additions & 2 deletions pkg/controller/preflightjob/collectors.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,17 @@ func remove(s []string, r string) []string {
func idForCollector(collector *troubleshootv1beta1.Collect) string {
if collector.ClusterInfo != nil {
return "cluster-info"
} else if collector.ClusterResources != nil {
}
if collector.ClusterResources != nil {
return "cluster-resources"
} else if collector.Secret != nil {
}
if collector.Secret != nil {
return fmt.Sprintf("secret-%s%s", collector.Secret.Namespace, collector.Secret.Name)
}
if collector.Logs != nil {
randomString := "abcdef" // TODO
return fmt.Sprintf("logs-%s%s", collector.Logs.Namespace, randomString)
}

return ""
}

0 comments on commit 270ccc0

Please sign in to comment.