Skip to content

Commit 678954e

Browse files
Made changes so that we get logs when a command starts no matter that it is finished or not
1 parent 9d12786 commit 678954e

File tree

6 files changed

+145
-22
lines changed

6 files changed

+145
-22
lines changed

cmd/minikube/cmd/root.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"path/filepath"
2424
"runtime"
2525
"strings"
26-
"time"
2726

2827
"github.com/spf13/cobra"
2928
"github.com/spf13/pflag"
@@ -84,8 +83,16 @@ var RootCmd = &cobra.Command{
8483
// Execute adds all child commands to the root command sets flags appropriately.
8584
// This is called by main.main(). It only needs to happen once to the rootCmd.
8685
func Execute() {
87-
defer audit.Log(time.Now())
88-
86+
auditID, err := audit.LogCommandStart()
87+
if err != nil {
88+
klog.Errorf("failed to log command start to audit: %v", err)
89+
}
90+
defer func() {
91+
err := audit.LogCommandEnd(auditID)
92+
if err != nil {
93+
klog.Errorf("failed to log command end to audit: %v", err)
94+
}
95+
}()
8996
// Check whether this is a windows binary (.exe) running inisde WSL.
9097
if runtime.GOOS == "windows" && detect.IsMicrosoftWSL() {
9198
var found = false

pkg/minikube/audit/audit.go

+72-6
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,25 @@ limitations under the License.
1717
package audit
1818

1919
import (
20+
"bufio"
21+
"encoding/json"
22+
"fmt"
2023
"os"
2124
"os/user"
2225
"strings"
26+
"sync"
2327
"time"
2428

29+
"github.com/google/uuid"
2530
"github.com/spf13/pflag"
2631
"github.com/spf13/viper"
27-
"k8s.io/klog/v2"
2832
"k8s.io/minikube/pkg/minikube/config"
33+
"k8s.io/minikube/pkg/minikube/constants"
2934
"k8s.io/minikube/pkg/version"
3035
)
3136

37+
var mutex sync.Mutex
38+
3239
// userName pulls the user flag, if empty gets the os username.
3340
func userName() string {
3441
u := viper.GetString(config.UserFlag)
@@ -52,14 +59,73 @@ func args() string {
5259
}
5360

5461
// Log details about the executed command.
55-
func Log(startTime time.Time) {
56-
if !shouldLog() {
57-
return
62+
func LogCommandStart() (string, error) {
63+
mutex.Lock()
64+
defer mutex.Unlock()
65+
if len(os.Args) < 2 || !shouldLog() {
66+
return "", nil
5867
}
59-
r := newRow(pflag.Arg(0), args(), userName(), version.GetVersion(), startTime, time.Now())
68+
id := uuid.New().String()
69+
r := newRow(pflag.Arg(0), args(), userName(), version.GetVersion(), time.Now(), id)
6070
if err := appendToLog(r); err != nil {
61-
klog.Warning(err)
71+
return "", err
72+
}
73+
return r.id, nil
74+
}
75+
76+
func LogCommandEnd(id string) error {
77+
mutex.Lock()
78+
defer mutex.Unlock()
79+
if id == "" {
80+
return nil
81+
}
82+
if currentLogFile == nil {
83+
if err := setLogFile(); err != nil {
84+
return fmt.Errorf("failed to set the log file: %v", err)
85+
}
86+
}
87+
_, err := currentLogFile.Seek(0, 0)
88+
if err != nil {
89+
return fmt.Errorf("failed to offset for the next Read or Write on currentLogFile: %v", err)
90+
}
91+
var logs []string
92+
s := bufio.NewScanner(currentLogFile)
93+
for s.Scan() {
94+
logs = append(logs, s.Text())
95+
}
96+
if err = s.Err(); err != nil {
97+
return fmt.Errorf("failed to read from audit file: %v", err)
98+
}
99+
rowSlice, err := logsToRows(logs)
100+
if err != nil {
101+
return fmt.Errorf("failed to convert logs to rows: %v", err)
102+
}
103+
auditContents := ""
104+
var entriesNeedsToUpdate int
105+
for _, v := range rowSlice {
106+
if v.id == id {
107+
v.endTime = time.Now().Format(constants.TimeFormat)
108+
v.Data = v.toMap()
109+
entriesNeedsToUpdate++
110+
}
111+
auditLog, err := json.Marshal(v)
112+
if err != nil {
113+
return err
114+
}
115+
auditContents += string(auditLog) + "\n"
116+
}
117+
if entriesNeedsToUpdate == 0 {
118+
return fmt.Errorf("failed to find a log row with id equals to %v", id)
119+
}
120+
_, err = currentLogFile.Seek(0, 0)
121+
if err != nil {
122+
return fmt.Errorf("failed to offset for the next Read or Write on currentLogFile: %v", err)
123+
}
124+
_, err = currentLogFile.Write([]byte(auditContents))
125+
if err != nil {
126+
return err
62127
}
128+
return nil
63129
}
64130

65131
// shouldLog returns if the command should be logged.

pkg/minikube/audit/audit_test.go

+46-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"os"
2121
"os/user"
2222
"testing"
23-
"time"
2423

2524
"github.com/spf13/pflag"
2625
"github.com/spf13/viper"
@@ -177,7 +176,27 @@ func TestAudit(t *testing.T) {
177176
})
178177

179178
// Check if logging with limited args causes a panic
180-
t.Run("Log", func(t *testing.T) {
179+
t.Run("LogCommandStart", func(t *testing.T) {
180+
oldArgs := os.Args
181+
defer func() { os.Args = oldArgs }()
182+
os.Args = []string{"minikube", "start"}
183+
184+
oldCommandLine := pflag.CommandLine
185+
defer func() {
186+
pflag.CommandLine = oldCommandLine
187+
pflag.Parse()
188+
}()
189+
mockArgs(t, os.Args)
190+
auditID, err := LogCommandStart()
191+
if auditID == "" {
192+
t.Fatal("audit ID should not be empty")
193+
}
194+
if err != nil {
195+
t.Fatal(err)
196+
}
197+
})
198+
199+
t.Run("LogCommandEnd", func(t *testing.T) {
181200
oldArgs := os.Args
182201
defer func() { os.Args = oldArgs }()
183202
os.Args = []string{"minikube"}
@@ -188,8 +207,32 @@ func TestAudit(t *testing.T) {
188207
pflag.Parse()
189208
}()
190209
mockArgs(t, os.Args)
210+
auditID, err := LogCommandStart()
211+
if err != nil {
212+
t.Fatal("start failed")
213+
}
214+
err = LogCommandEnd(auditID)
191215

192-
Log(time.Now())
216+
if err != nil {
217+
t.Fatal(err)
218+
}
219+
})
220+
221+
t.Run("LogCommandEnd", func(t *testing.T) {
222+
oldArgs := os.Args
223+
defer func() { os.Args = oldArgs }()
224+
os.Args = []string{"minikube"}
225+
226+
oldCommandLine := pflag.CommandLine
227+
defer func() {
228+
pflag.CommandLine = oldCommandLine
229+
pflag.Parse()
230+
}()
231+
mockArgs(t, os.Args)
232+
err := LogCommandEnd("non-existing-id")
233+
if err == nil {
234+
t.Fatal("function LogCommandEnd should return an error when a non-existing id is passed in it as an argument")
235+
}
193236
})
194237
}
195238

pkg/minikube/audit/logFile_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"testing"
2424
"time"
2525

26+
"github.com/google/uuid"
2627
"k8s.io/minikube/pkg/minikube/localpath"
2728
)
2829

@@ -48,7 +49,7 @@ func TestLogFile(t *testing.T) {
4849
defer func() { currentLogFile = &oldLogFile }()
4950
currentLogFile = f
5051

51-
r := newRow("start", "-v", "user1", "v0.17.1", time.Now(), time.Now())
52+
r := newRow("start", "-v", "user1", "v0.17.1", time.Now(), uuid.New().String())
5253
if err := appendToLog(r); err != nil {
5354
t.Fatalf("Error appendingToLog: %v", err)
5455
}

pkg/minikube/audit/row.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type row struct {
3737
startTime string
3838
user string
3939
version string
40+
id string
4041
Data map[string]string `json:"data"`
4142
}
4243

@@ -55,6 +56,7 @@ func (e *row) assignFields() {
5556
e.startTime = e.Data["startTime"]
5657
e.user = e.Data["user"]
5758
e.version = e.Data["version"]
59+
e.id = e.Data["id"]
5860
}
5961

6062
// toMap combines fields into a string map,
@@ -68,30 +70,31 @@ func (e *row) toMap() map[string]string {
6870
"startTime": e.startTime,
6971
"user": e.user,
7072
"version": e.version,
73+
"id": e.id,
7174
}
7275
}
7376

7477
// newRow creates a new audit row.
75-
func newRow(command string, args string, user string, version string, startTime time.Time, endTime time.Time, profile ...string) *row {
78+
func newRow(command string, args string, user string, version string, startTime time.Time, id string, profile ...string) *row {
7679
p := viper.GetString(config.ProfileName)
7780
if len(profile) > 0 {
7881
p = profile[0]
7982
}
8083
return &row{
8184
args: args,
8285
command: command,
83-
endTime: endTime.Format(constants.TimeFormat),
8486
profile: p,
8587
startTime: startTime.Format(constants.TimeFormat),
8688
user: user,
8789
version: version,
90+
id: id,
8891
}
8992
}
9093

9194
// toFields converts a row to an array of fields,
9295
// to be used when converting to a table.
9396
func (e *row) toFields() []string {
94-
return []string{e.command, e.args, e.profile, e.user, e.version, e.startTime, e.endTime}
97+
return []string{e.command, e.args, e.profile, e.user, e.version, e.startTime, e.endTime, e.id}
9598
}
9699

97100
// logsToRows converts audit logs into arrays of rows.

pkg/minikube/audit/row_test.go

+9-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"testing"
2424
"time"
2525

26+
"github.com/google/uuid"
2627
"k8s.io/minikube/pkg/minikube/constants"
2728
)
2829

@@ -36,8 +37,10 @@ func TestRow(t *testing.T) {
3637
stFormatted := st.Format(constants.TimeFormat)
3738
et := time.Now()
3839
etFormatted := et.Format(constants.TimeFormat)
40+
id := uuid.New().String()
3941

40-
r := newRow(c, a, u, v, st, et, p)
42+
r := newRow(c, a, u, v, st, id, p)
43+
r.endTime = etFormatted
4144

4245
t.Run("NewRow", func(t *testing.T) {
4346
tests := []struct {
@@ -51,7 +54,7 @@ func TestRow(t *testing.T) {
5154
{"user", r.user, u},
5255
{"version", r.version, v},
5356
{"startTime", r.startTime, stFormatted},
54-
{"endTime", r.endTime, etFormatted},
57+
{"id", r.id, id},
5558
}
5659

5760
for _, tt := range tests {
@@ -83,7 +86,7 @@ func TestRow(t *testing.T) {
8386
{"user", u},
8487
{"version", v},
8588
{"startTime", stFormatted},
86-
{"endTime", etFormatted},
89+
{"id", id},
8790
}
8891

8992
for _, tt := range tests {
@@ -97,7 +100,7 @@ func TestRow(t *testing.T) {
97100
t.Run("toFields", func(t *testing.T) {
98101
got := r.toFields()
99102
gotString := strings.Join(got, ",")
100-
want := []string{c, a, p, u, v, stFormatted, etFormatted}
103+
want := []string{c, a, p, u, v, stFormatted, etFormatted, id}
101104
wantString := strings.Join(want, ",")
102105

103106
if gotString != wantString {
@@ -106,7 +109,7 @@ func TestRow(t *testing.T) {
106109
})
107110

108111
t.Run("assignFields", func(t *testing.T) {
109-
l := fmt.Sprintf(`{"data":{"args":"%s","command":"%s","endTime":"%s","profile":"%s","startTime":"%s","user":"%s","version":"v0.17.1"},"datacontenttype":"application/json","id":"bc6ec9d4-0d08-4b57-ac3b-db8d67774768","source":"https://minikube.sigs.k8s.io/","specversion":"1.0","type":"io.k8s.sigs.minikube.audit"}`, a, c, etFormatted, p, stFormatted, u)
112+
l := fmt.Sprintf(`{"data":{"args":"%s","command":"%s","id":"%s","profile":"%s","startTime":"%s","user":"%s","version":"v0.17.1"},"datacontenttype":"application/json","id":"bc6ec9d4-0d08-4b57-ac3b-db8d67774768","source":"https://minikube.sigs.k8s.io/","specversion":"1.0","type":"io.k8s.sigs.minikube.audit"}`, a, c, id, p, stFormatted, u)
110113

111114
r := &row{}
112115
if err := json.Unmarshal([]byte(l), r); err != nil {
@@ -126,7 +129,7 @@ func TestRow(t *testing.T) {
126129
{"user", r.user, u},
127130
{"version", r.version, v},
128131
{"startTime", r.startTime, stFormatted},
129-
{"endTime", r.endTime, etFormatted},
132+
{"id", r.id, id},
130133
}
131134

132135
for _, tt := range tests {

0 commit comments

Comments
 (0)