-
Notifications
You must be signed in to change notification settings - Fork 0
/
logs.go
211 lines (184 loc) · 6.25 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package print
import (
"encoding/json"
"errors"
"fmt"
"os"
"strconv"
"time"
"github.com/jedib0t/go-pretty/table"
"github.com/jedib0t/go-pretty/text"
"github.com/snapmaster-io/snap/pkg/utils"
)
// ActiveSnapActionsLog defines the fields to unmarshal for action logs
type ActiveSnapActionsLog struct {
Provider string `json:"provider"`
Action string `json:"action"`
State string `json:"state"`
Output ActiveSnapActionsLogOutput `json:"output"`
}
// ActiveSnapActionsLogOutput defines the fields to unmarshal for action logs
type ActiveSnapActionsLogOutput struct {
Status string `json:"status"`
Message string `json:"message"`
Data map[string]interface{} `json:"data"`
}
/*
type ActiveSnapActionsLogOutput struct {
Stdout string `json:"stdout"`
Stderr string `json:"stderr"`
Error string `json:"error"`
}
*/
// ActiveSnapLog defines the fields to unmarshal for an active snap's logs
type ActiveSnapLog struct {
LogID int64 `json:"timestamp"`
ActiveSnapID string `json:"activeSnapId"`
SnapID string `json:"snapID"`
State string `json:"state"`
Trigger string `json:"trigger"`
Event string `json:"event"`
Actions []ActiveSnapActionsLog `json:"actions"`
}
// ActiveSnapLogsResponse defines the fields to unmarshal from getting all logs for an active snap
type ActiveSnapLogsResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Data []ActiveSnapLog `json:"data"`
}
// ActiveSnapLogsTable prints out the active snap logs response as a table
func ActiveSnapLogsTable(response []byte) {
// extract the logs and check for errors
activeSnapLogs, err := extractLogs(response)
if err != nil {
return
}
// grab the SnapIP, ActiveSnapID, and Trigger from the first record
activeSnapInstance := activeSnapLogs[0]
activeSnapID := activeSnapInstance.ActiveSnapID
snapID := activeSnapInstance.SnapID
trigger := activeSnapInstance.Trigger
event := activeSnapInstance.Event
// write out the table of properties
t := table.NewWriter()
t.SetTitle(fmt.Sprintf(
"Logs for Snap ID %s\nActive Snap ID %s, triggered by %s:%s",
snapID, activeSnapID, trigger, event))
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"Log ID", "Timestamp", "State"})
for _, logEntry := range activeSnapLogs {
timestamp := time.Unix(logEntry.LogID/1000, 0)
t.AppendRow(table.Row{logEntry.LogID, timestamp, logEntry.State})
}
t.SetStyle(tableStyle)
t.Style().Title.Align = text.AlignCenter
t.Render()
}
// ActiveSnapLogDetails prints out the active log details response
func ActiveSnapLogDetails(response []byte, logID string, format string) {
// extract the logs and check for errors
activeSnapLogs, err := extractLogs(response)
if err != nil {
return
}
// grab the SnapIP, ActiveSnapID, and Trigger from the first record
activeSnapInstance := activeSnapLogs[0]
activeSnapID := activeSnapInstance.ActiveSnapID
snapID := activeSnapInstance.SnapID
var logEntry ActiveSnapLog
// find the entry with the right logID
found := false
for k, v := range activeSnapLogs {
logIDasInt64, _ := strconv.ParseInt(logID, 10, 64)
if v.LogID == logIDasInt64 {
logEntry = activeSnapLogs[k]
found = true
}
}
// check for log entry not found
if found == false {
utils.PrintError(fmt.Sprintf("log ID %s not found for active Snap ID %s", logID, activeSnapID))
return
}
// write out general information
t := table.NewWriter()
t.SetTitle("Action log details")
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"Snap ID", "Active Snap ID", "Log ID", "State"})
t.AppendRow(table.Row{snapID, activeSnapID, logID, logEntry.State})
t.SetStyle(tableStyle)
t.Style().Title.Align = text.AlignCenter
t.Render()
fmt.Println("\nAction details:")
// write out the table of properties
for _, action := range logEntry.Actions {
fmt.Println()
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
if action.Output.Status != "success" {
t.AppendHeader(table.Row{"Provider", "Action", "State", "Message"})
t.AppendRow(table.Row{action.Provider, action.Action, action.State, action.Output.Message})
} else {
t.AppendHeader(table.Row{"Provider", "Action", "State"})
t.AppendRow(table.Row{action.Provider, action.Action, action.State})
}
t.SetStyle(actionTableStyle)
t.Render()
// print the output of the operation
printOutput(action.Output)
}
}
// do some common processing on the ActiveSnapLogResponse, and extract the logs
func extractLogs(response []byte) ([]ActiveSnapLog, error) {
// unmarshal into the ActiveSnapLogsResponse struct, to flatten the property set
var activeSnapLogsResponse ActiveSnapLogsResponse
json.Unmarshal(response, &activeSnapLogsResponse)
// check for errors
if activeSnapLogsResponse.Status == "error" {
utils.PrintStatus(activeSnapLogsResponse.Status, activeSnapLogsResponse.Message)
return nil, errors.New("Error encountered")
}
// extract the active snap logs
activeSnapLogs := activeSnapLogsResponse.Data
// check for no rows
if len(activeSnapLogs) < 1 {
utils.PrintError("no logs found for this active snap")
return nil, errors.New("No logs found for this active snap")
}
return activeSnapLogs, nil
}
// print the output for the action
func printOutput(output ActiveSnapActionsLogOutput) {
data := output.Data
if output.Status == "success" {
// if the action supports the stdout/stderr protocol, print those out
if data["stdout"] != nil || data["stderr"] != nil {
if data["stdout"] != nil {
// write out stdout
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"Stdout"})
t.SetStyle(tableStyle)
t.Render()
fmt.Printf("%s\n", data["stdout"])
}
if data["stderr"] != nil {
// write out stderr
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"Stderr"})
t.SetStyle(tableStyle)
t.Render()
fmt.Printf("%s\n", data["stderr"])
}
} else {
// print out the JSON response
payload, err := json.Marshal(data)
if err != nil {
utils.PrintErrorMessage("could not serialize payload into JSON", err)
} else {
utils.PrintJSON(payload)
}
}
}
}