forked from feedhenry/fh-system-dump-tool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
logs.go
126 lines (118 loc) · 4.01 KB
/
logs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"bytes"
"os/exec"
"path/filepath"
"strconv"
)
// LoggableResource describes an OpenShift resource that produces logs. Even
// though oc logs can fetch logs for build, buildconfig, deploymentconfig and
// pod resources, eventually the first three are just shortcuts to a certain
// pod. For dump purposes, it is enough to fetch logs of all pods.
type LoggableResource struct {
Project string
// Type should be one of: build, buildconfig, deploymentconfig or pod,
// or an alias to one of those.
Type string
// Name is generally a pod name, but could be a reference to one of the
// other types understood by oc logs.
Name string
// Container is required for pods with more than one container.
Container string
}
// GetFetchLogsTasks sends tasks to fetch current and previous logs of all
// resources in all projects.
func GetFetchLogsTasks(tasks chan<- Task, runner Runner, projects, resources []string, maxLines int) {
for _, p := range projects {
for _, rtype := range resources {
names, err := GetResourceNames(runner, p, rtype)
if err != nil {
tasks <- NewError(err)
continue
}
for _, name := range names {
getFetchLogsTasksPerResource(tasks, runner, p, rtype, name, maxLines)
}
}
}
}
// getFetchLogsTasksPerResource sends tasks to fetch current and previous logs
// of the named resource of type rtype in the given project. Pod resources
// produce tasks for each container in the pod.
func getFetchLogsTasksPerResource(tasks chan<- Task, runner Runner, project, rtype, name string, maxLines int) {
var (
containers []string
)
switch rtype {
case "po", "pod", "pods":
var err error
containers, err = GetPodContainers(runner, project, name)
if err != nil {
tasks <- NewError(err)
return
}
default:
// For types other than pod, we can treat them as if
// they had a single unnamed container, for the name
// doesn't matter when fetching logs.
containers = []string{""}
}
for _, container := range containers {
r := LoggableResource{
Project: project,
Type: rtype,
Name: name,
Container: container,
}
// Send task to fetch current logs.
tasks <- FetchLogs(runner, r, maxLines)
// Send task to fetch previous logs.
tasks <- FetchPreviousLogs(runner, r, maxLines)
}
}
// GetPodContainers returns a list of container names for the named pod in the
// project.
func GetPodContainers(runner Runner, project, name string) ([]string, error) {
cmd := exec.Command("oc", "-n", project, "get", "pod", name, "-o=jsonpath={.spec.containers[*].name}")
var b bytes.Buffer
cmd.Stdout = &b
if err := runner.Run(cmd, filepath.Join("projects", project, "pods", name, "container-names")); err != nil {
return nil, err
}
return readSpaceSeparated(&b)
}
// FetchLogs is a task factory for tasks that fetch the logs of a
// LoggableResource. Set maxLines to limit how many lines are fetched. Logs are
// written to out and eventual error messages go to errOut.
func FetchLogs(r Runner, resource LoggableResource, maxLines int) Task {
return ocLogs(r, resource, maxLines, nil, "logs")
}
// FetchPreviousLogs is like FetchLogs, but for the previous version of a
// resource.
func FetchPreviousLogs(r Runner, resource LoggableResource, maxLines int) Task {
return ocLogs(r, resource, maxLines, []string{"--previous"}, "logs-previous")
}
// ocLogs fetches logs from an OpenShift resource using oc.
func ocLogs(r Runner, resource LoggableResource, maxLines int, extraArgs []string, what string) Task {
return func() error {
name := resource.Name
if resource.Type != "" {
name = resource.Type + "/" + name
}
cmd := exec.Command("oc", append([]string{
"-n", resource.Project,
"logs", name,
"-c", resource.Container,
"--tail", strconv.Itoa(maxLines)},
extraArgs...)...)
filename := resource.Name
if resource.Type != "" {
filename = resource.Type + "_" + filename
}
if resource.Container != "" {
filename += "_" + resource.Container
}
path := filepath.Join("projects", resource.Project, what, filename+".logs")
return r.Run(cmd, path)
}
}