/
logs.go
106 lines (90 loc) · 2.96 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
/*
Copyright 2020 NetFoundry Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package zitilib_actions
import (
"fmt"
"github.com/openziti/fablab/kernel/libssh"
"os"
"path/filepath"
"github.com/openziti/fablab/kernel/model"
"github.com/openziti/foundation/v2/info"
"github.com/sirupsen/logrus"
)
func Logs() model.Action {
return &logs{}
}
func (self *logs) Execute(run model.Run) error {
if !run.GetModel().IsBound() {
return fmt.Errorf("model not bound")
}
snapshot := fmt.Sprintf("%d", info.NowInMilliseconds())
for rn, r := range run.GetModel().Regions {
for hn, h := range r.Hosts {
ssh := h.NewSshConfigFactory()
if err := self.forHost(snapshot, rn, hn, ssh); err != nil {
return fmt.Errorf("error retrieving logs for [%s/%s] (%w)", rn, hn, err)
}
}
}
return nil
}
func (self *logs) forHost(snapshot, rn, hn string, ssh libssh.SshConfigFactory) error {
path := filepath.Join(model.AllocateForensicScenario(snapshot, "logs"), rn, hn)
if err := os.MkdirAll(path, os.ModePerm); err != nil {
return fmt.Errorf("error creating logs path [%s] for host [%s/%s] (%w)", path, rn, hn, err)
}
logrus.Infof("=> [%s]", path)
fis, err := libssh.RemoteFileList(ssh, ".")
if err != nil {
return fmt.Errorf("error retrieving home directory for host [%s/%s] (%w)", rn, hn, err)
}
hasLogs := false
for _, fi := range fis {
if fi.Name() == "logs" && fi.IsDir() {
hasLogs = true
break
}
}
if hasLogs {
if err := self.forHostDir(path, "logs", ssh); err != nil {
return fmt.Errorf("error retrieving files from host [%s/%s] (%w)", rn, hn, err)
}
}
return nil
}
func (self *logs) forHostDir(localPath, remotePath string, ssh libssh.SshConfigFactory) error {
fis, err := libssh.RemoteFileList(ssh, remotePath)
if err != nil {
return err
}
var paths []string
for _, fi := range fis {
if fi.IsDir() {
nextLocalPath := filepath.Join(localPath, fi.Name())
if err := os.MkdirAll(nextLocalPath, os.ModePerm); err != nil {
return fmt.Errorf("error creating local path [%s] (%w)", nextLocalPath, err)
}
nextRemotePath := filepath.Join(remotePath, fi.Name())
if err := self.forHostDir(nextLocalPath, nextRemotePath, ssh); err != nil {
return fmt.Errorf("error recursing into tree (%w)", err)
}
} else {
paths = append(paths, filepath.Join(remotePath, fi.Name()))
}
}
if err := libssh.RetrieveRemoteFiles(ssh, localPath, paths...); err != nil {
return fmt.Errorf("error retrieving from [%s] (%w)", localPath, err)
}
return nil
}
type logs struct{}