forked from canonical/lxd
/
container_logs.go
102 lines (80 loc) · 2.33 KB
/
container_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
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"github.com/gorilla/mux"
"github.com/lxc/lxd/shared"
)
func containerLogsGet(d *Daemon, r *http.Request) Response {
/* Let's explicitly *not* try to do a containerLoadByName here. In some
* cases (e.g. when container creation failed), the container won't
* exist in the DB but it does have some log files on disk.
*
* However, we should check this name and ensure it's a valid container
* name just so that people can't list arbitrary directories.
*/
name := mux.Vars(r)["name"]
if err := containerValidName(name); err != nil {
return BadRequest(err)
}
result := []string{}
dents, err := ioutil.ReadDir(shared.LogPath(name))
if err != nil {
return SmartError(err)
}
for _, f := range dents {
if !validLogFileName(f.Name()) {
continue
}
result = append(result, fmt.Sprintf("/%s/containers/%s/logs/%s", shared.APIVersion, name, f.Name()))
}
return SyncResponse(true, result)
}
var containerLogsCmd = Command{
name: "containers/{name}/logs",
get: containerLogsGet,
}
func validLogFileName(fname string) bool {
/* Let's just require that the paths be relative, so that we don't have
* to deal with any escaping or whatever.
*/
return fname == "lxc.log" ||
fname == "lxc.conf" ||
strings.HasPrefix(fname, "migration_") ||
strings.HasPrefix(fname, "snapshot_") ||
strings.HasPrefix(fname, "exec_")
}
func containerLogGet(d *Daemon, r *http.Request) Response {
name := mux.Vars(r)["name"]
file := mux.Vars(r)["file"]
if err := containerValidName(name); err != nil {
return BadRequest(err)
}
if !validLogFileName(file) {
return BadRequest(fmt.Errorf("log file name %s not valid", file))
}
ent := fileResponseEntry{
path: shared.LogPath(name, file),
filename: file,
}
return FileResponse(r, []fileResponseEntry{ent}, nil, false)
}
func containerLogDelete(d *Daemon, r *http.Request) Response {
name := mux.Vars(r)["name"]
file := mux.Vars(r)["file"]
if err := containerValidName(name); err != nil {
return BadRequest(err)
}
if !validLogFileName(file) {
return BadRequest(fmt.Errorf("log file name %s not valid", file))
}
return SmartError(os.Remove(shared.LogPath(name, file)))
}
var containerLogCmd = Command{
name: "containers/{name}/logs/{file}",
get: containerLogGet,
delete: containerLogDelete,
}