Skip to content

Commit f30fcc0

Browse files
authored
Add event logger type and function to set event context for writer (#5937)
* add event logger type * fix import cycle and tests
1 parent 3864896 commit f30fcc0

File tree

6 files changed

+203
-5
lines changed

6 files changed

+203
-5
lines changed

pkg/skaffold/event/v2/config.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2021 The Skaffold Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v2
18+
19+
import (
20+
latestV1 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest/v1"
21+
)
22+
23+
type Config interface {
24+
GetKubeContext() string
25+
AutoBuild() bool
26+
AutoDeploy() bool
27+
AutoSync() bool
28+
GetPipelines() []latestV1.Pipeline
29+
}

pkg/skaffold/event/v2/event.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030

3131
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
3232
sErrors "github.com/GoogleContainerTools/skaffold/pkg/skaffold/errors"
33-
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/event"
3433
proto "github.com/GoogleContainerTools/skaffold/proto/v2"
3534
)
3635

@@ -69,7 +68,7 @@ type eventHandler struct {
6968
logLock sync.Mutex
7069
applicationLogs []proto.Event
7170
applicationLogsLock sync.Mutex
72-
cfg event.Config
71+
cfg Config
7372

7473
iteration int
7574
state proto.State
@@ -179,7 +178,7 @@ func (ev *eventHandler) forEachApplicationLog(callback func(*proto.Event) error)
179178
return ev.forEach(&ev.applicationLogListeners, &ev.applicationLogs, &ev.applicationLogsLock, callback)
180179
}
181180

182-
func emptyState(cfg event.Config) proto.State {
181+
func emptyState(cfg Config) proto.State {
183182
builds := map[string]string{}
184183
for _, p := range cfg.GetPipelines() {
185184
for _, a := range p.Build.Artifacts {
@@ -272,7 +271,7 @@ func emptyStatusCheckState() *proto.StatusCheckState {
272271
}
273272

274273
// InitializeState instantiates the global state of the skaffold runner, as well as the event log.
275-
func InitializeState(cfg event.Config) {
274+
func InitializeState(cfg Config) {
276275
handler.cfg = cfg
277276
handler.setState(emptyState(cfg))
278277
}
@@ -286,7 +285,7 @@ func AutoTriggerDiff(phase constants.Phase, val bool) (bool, error) {
286285
case constants.Deploy:
287286
return val != handler.getState().DeployState.AutoTrigger, nil
288287
default:
289-
return false, fmt.Errorf("unknown phase %v not found in handler state", phase)
288+
return false, fmt.Errorf("unknown Phase %v not found in handler state", phase)
290289
}
291290
}
292291

pkg/skaffold/event/v2/logger.go

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
Copyright 2021 The Skaffold Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v2
18+
19+
import (
20+
"fmt"
21+
"io"
22+
23+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
24+
proto "github.com/GoogleContainerTools/skaffold/proto/v2"
25+
)
26+
27+
type logger struct {
28+
Phase constants.Phase
29+
SubtaskID string
30+
Origin string
31+
}
32+
33+
func NewLogger(phase constants.Phase, subtaskID, origin string) io.Writer {
34+
return logger{
35+
Phase: phase,
36+
SubtaskID: subtaskID,
37+
Origin: origin,
38+
}
39+
}
40+
41+
func (l logger) Write(p []byte) (int, error) {
42+
handler.handleSkaffoldLogEvent(&proto.SkaffoldLogEvent{
43+
TaskId: fmt.Sprintf("%s-%d", l.Phase, handler.iteration),
44+
SubtaskId: l.SubtaskID,
45+
Origin: l.Origin,
46+
Level: 0,
47+
Message: string(p),
48+
})
49+
50+
return len(p), nil
51+
}
52+
53+
func (ev *eventHandler) handleSkaffoldLogEvent(e *proto.SkaffoldLogEvent) {
54+
ev.handle(&proto.Event{
55+
EventType: &proto.Event_SkaffoldLogEvent{
56+
SkaffoldLogEvent: e,
57+
},
58+
})
59+
}

pkg/skaffold/event/v2/logger_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
Copyright 2021 The Skaffold Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v2
18+
19+
import (
20+
"testing"
21+
22+
latestV1 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest/v1"
23+
"github.com/GoogleContainerTools/skaffold/proto/enums"
24+
proto "github.com/GoogleContainerTools/skaffold/proto/v2"
25+
)
26+
27+
func TestHandleSkaffoldLogEvent(t *testing.T) {
28+
testHandler := newHandler()
29+
testHandler.state = emptyState(mockCfg([]latestV1.Pipeline{{}}, "test"))
30+
31+
messages := []string{
32+
"hi!",
33+
"how's it going",
34+
"hope you're well",
35+
"this is a skaffold test",
36+
}
37+
38+
// ensure that messages sent through the SkaffoldLog function are populating the event log
39+
for _, message := range messages {
40+
testHandler.handleSkaffoldLogEvent(&proto.SkaffoldLogEvent{
41+
TaskId: "Test-0",
42+
SubtaskId: "1",
43+
Origin: "skaffold-test",
44+
Level: enums.LogLevel_INFO,
45+
Message: message,
46+
})
47+
}
48+
wait(t, func() bool {
49+
testHandler.logLock.Lock()
50+
logLen := len(testHandler.eventLog)
51+
testHandler.logLock.Unlock()
52+
return logLen == len(messages)
53+
})
54+
}

pkg/skaffold/output/output.go

+16
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import (
2020
"io"
2121
"io/ioutil"
2222
"os"
23+
24+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
25+
eventV2 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event/v2"
2326
)
2427

2528
type skaffoldWriter struct {
@@ -77,3 +80,16 @@ func GetUnderlyingWriter(out io.Writer) io.Writer {
7780
}
7881
return out
7982
}
83+
84+
// WithEventContext will return a new skaffoldWriter with the given parameters to be used for the event writer.
85+
// If the passed io.Writer is not a skaffoldWriter, then it is simply returned.
86+
func WithEventContext(out io.Writer, phase constants.Phase, subtaskID, origin string) io.Writer {
87+
if sw, isSW := out.(skaffoldWriter); isSW {
88+
return skaffoldWriter{
89+
MainWriter: sw.MainWriter,
90+
EventWriter: eventV2.NewLogger(phase, subtaskID, origin),
91+
}
92+
}
93+
94+
return out
95+
}

pkg/skaffold/output/output_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"os"
2424
"testing"
2525

26+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
27+
eventV2 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event/v2"
2628
"github.com/GoogleContainerTools/skaffold/testutil"
2729
)
2830

@@ -116,3 +118,42 @@ func TestGetUnderlyingWriter(t *testing.T) {
116118
})
117119
}
118120
}
121+
122+
func TestWithEventContext(t *testing.T) {
123+
tests := []struct {
124+
name string
125+
writer io.Writer
126+
phase constants.Phase
127+
subtaskID string
128+
origin string
129+
130+
expected io.Writer
131+
}{
132+
{
133+
name: "skaffoldWriter update info",
134+
writer: skaffoldWriter{
135+
MainWriter: ioutil.Discard,
136+
EventWriter: eventV2.NewLogger(constants.Build, "1", "skaffold-test"),
137+
},
138+
phase: constants.Test,
139+
subtaskID: "2",
140+
origin: "skaffold-test-change",
141+
expected: skaffoldWriter{
142+
MainWriter: ioutil.Discard,
143+
EventWriter: eventV2.NewLogger(constants.Test, "2", "skaffold-test-change"),
144+
},
145+
},
146+
{
147+
name: "non skaffoldWriter returns same",
148+
writer: ioutil.Discard,
149+
expected: ioutil.Discard,
150+
},
151+
}
152+
153+
for _, test := range tests {
154+
testutil.Run(t, test.name, func(t *testutil.T) {
155+
got := WithEventContext(test.writer, test.phase, test.subtaskID, test.origin)
156+
t.CheckDeepEqual(test.expected, got)
157+
})
158+
}
159+
}

0 commit comments

Comments
 (0)