Add timestamp for events

Relates-To: #339
Change-Id: Iec939e167b6ae3c72aa31e102407d0fffc370766
This commit is contained in:
Vladislav Kuzmin 2020-10-15 16:49:01 +04:00
parent f681da04f2
commit f9f8c43e8a
5 changed files with 113 additions and 128 deletions

View File

@ -83,22 +83,16 @@ func (c *Executor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
return return
} }
evtCh <- events.Event{ evtCh <- events.NewEvent().WithIsogenEvent(events.IsogenEvent{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{
Operation: events.IsogenStart, Operation: events.IsogenStart,
Message: "starting ISO generation", Message: "starting ISO generation",
}, })
}
if opts.DryRun { if opts.DryRun {
log.Print("command isogen will be executed") log.Print("command isogen will be executed")
evtCh <- events.Event{ evtCh <- events.NewEvent().WithIsogenEvent(events.IsogenEvent{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{
Operation: events.IsogenEnd, Operation: events.IsogenEnd,
}, })
}
return return
} }
@ -131,26 +125,20 @@ func (c *Executor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
return return
} }
evtCh <- events.Event{ evtCh <- events.NewEvent().WithIsogenEvent(events.IsogenEvent{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{
Operation: events.IsogenValidation, Operation: events.IsogenValidation,
Message: "image is generated successfully, verifying artifacts", Message: "image is generated successfully, verifying artifacts",
}, })
}
err = verifyArtifacts(c.imgConf) err = verifyArtifacts(c.imgConf)
if err != nil { if err != nil {
handleError(evtCh, err) handleError(evtCh, err)
return return
} }
evtCh <- events.Event{ evtCh <- events.NewEvent().WithIsogenEvent(events.IsogenEvent{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{
Operation: events.IsogenEnd, Operation: events.IsogenEnd,
Message: "iso generation is complete and artifacts verified", Message: "iso generation is complete and artifacts verified",
}, })
}
} }
// Validate executor configuration and documents // Validate executor configuration and documents
@ -166,10 +154,7 @@ func (c *Executor) Render(w io.Writer, _ ifc.RenderOptions) error {
} }
func handleError(ch chan<- events.Event, err error) { func handleError(ch chan<- events.Event, err error) {
ch <- events.Event{ ch <- events.NewEvent().WithErrorEvent(events.ErrorEvent{
Type: events.ErrorType,
ErrorEvent: events.ErrorEvent{
Error: err, Error: err,
}, })
}
} }

View File

@ -16,6 +16,7 @@ package isogen
import ( import (
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -109,24 +110,15 @@ func TestExecutorRun(t *testing.T) {
waitUntilFinished: func() error { return nil }, waitUntilFinished: func() error { return nil },
}, },
expectedEvt: []events.Event{ expectedEvt: []events.Event{
{ events.NewEvent().WithIsogenEvent(events.IsogenEvent{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{
Operation: events.IsogenStart, Operation: events.IsogenStart,
}, }),
}, events.NewEvent().WithIsogenEvent(events.IsogenEvent{
{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{
Operation: events.IsogenValidation, Operation: events.IsogenValidation,
}, }),
}, events.NewEvent().WithIsogenEvent(events.IsogenEvent{
{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{
Operation: events.IsogenEnd, Operation: events.IsogenEnd,
}, }),
},
}, },
}, },
{ {
@ -140,12 +132,9 @@ func TestExecutorRun(t *testing.T) {
}, },
expectedEvt: []events.Event{ expectedEvt: []events.Event{
{ events.NewEvent().WithIsogenEvent(events.IsogenEvent{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{
Operation: events.IsogenStart, Operation: events.IsogenStart,
}, }),
},
wrapError(container.ErrRunContainerCommand{Cmd: "super fail"}), wrapError(container.ErrRunContainerCommand{Cmd: "super fail"}),
}, },
}, },
@ -163,24 +152,27 @@ func TestExecutorRun(t *testing.T) {
go executor.Run(ch, ifc.RunOptions{}) go executor.Run(ch, ifc.RunOptions{})
var actualEvt []events.Event var actualEvt []events.Event
for evt := range ch { for evt := range ch {
// Skip timestamp for comparison
evt.Timestamp = time.Time{}
if evt.Type == events.IsogenType { if evt.Type == events.IsogenType {
// Set message to empty string, so it's not compared // Set message to empty string, so it's not compared
evt.IsogenEvent.Message = "" evt.IsogenEvent.Message = ""
} }
actualEvt = append(actualEvt, evt) actualEvt = append(actualEvt, evt)
} }
for i := range tt.expectedEvt {
// Skip timestamp for comparison
tt.expectedEvt[i].Timestamp = time.Time{}
}
assert.Equal(t, tt.expectedEvt, actualEvt) assert.Equal(t, tt.expectedEvt, actualEvt)
}) })
} }
} }
func wrapError(err error) events.Event { func wrapError(err error) events.Event {
return events.Event{ return events.NewEvent().WithErrorEvent(events.ErrorEvent{
Type: events.ErrorType,
ErrorEvent: events.ErrorEvent{
Error: err, Error: err,
}, })
}
} }
func testBundleFactory(path string) document.BundleFactoryFunc { func testBundleFactory(path string) document.BundleFactoryFunc {

View File

@ -84,13 +84,10 @@ func (c *ClusterctlExecutor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
} }
func (c *ClusterctlExecutor) move(opts ifc.RunOptions, evtCh chan events.Event) { func (c *ClusterctlExecutor) move(opts ifc.RunOptions, evtCh chan events.Event) {
evtCh <- events.Event{ evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlMoveStart, Operation: events.ClusterctlMoveStart,
Message: "starting clusterctl move executor", Message: "starting clusterctl move executor",
}, })
}
ns := c.options.MoveOptions.Namespace ns := c.options.MoveOptions.Namespace
kubeConfigFile, cleanup, err := c.kubecfg.GetFile() kubeConfigFile, cleanup, err := c.kubecfg.GetFile()
if err != nil { if err != nil {
@ -113,23 +110,17 @@ func (c *ClusterctlExecutor) move(opts ifc.RunOptions, evtCh chan events.Event)
} }
} }
evtCh <- events.Event{ evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlMoveEnd, Operation: events.ClusterctlMoveEnd,
Message: "clusterctl move completed successfully", Message: "clusterctl move completed successfully",
}, })
}
} }
func (c *ClusterctlExecutor) init(opts ifc.RunOptions, evtCh chan events.Event) { func (c *ClusterctlExecutor) init(opts ifc.RunOptions, evtCh chan events.Event) {
evtCh <- events.Event{ evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitStart, Operation: events.ClusterctlInitStart,
Message: "starting clusterctl init executor", Message: "starting clusterctl init executor",
}, })
}
kubeConfigFile, cleanup, err := c.kubecfg.GetFile() kubeConfigFile, cleanup, err := c.kubecfg.GetFile()
if err != nil { if err != nil {
c.handleErr(err, evtCh) c.handleErr(err, evtCh)
@ -141,13 +132,10 @@ func (c *ClusterctlExecutor) init(opts ifc.RunOptions, evtCh chan events.Event)
if opts.DryRun { if opts.DryRun {
// TODO (dukov) add more details to dry-run // TODO (dukov) add more details to dry-run
log.Print("command 'clusterctl init' is going to be executed") log.Print("command 'clusterctl init' is going to be executed")
evtCh <- events.Event{ evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitEnd, Operation: events.ClusterctlInitEnd,
Message: "clusterctl init dry-run completed successfully", Message: "clusterctl init dry-run completed successfully",
}, })
}
return return
} }
// Use cluster name as context in kubeconfig file // Use cluster name as context in kubeconfig file
@ -155,22 +143,16 @@ func (c *ClusterctlExecutor) init(opts ifc.RunOptions, evtCh chan events.Event)
if err != nil { if err != nil {
c.handleErr(err, evtCh) c.handleErr(err, evtCh)
} }
evtCh <- events.Event{ evtCh <- events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitEnd, Operation: events.ClusterctlInitEnd,
Message: "clusterctl init completed successfully", Message: "clusterctl init completed successfully",
}, })
}
} }
func (c *ClusterctlExecutor) handleErr(err error, evtCh chan events.Event) { func (c *ClusterctlExecutor) handleErr(err error, evtCh chan events.Event) {
evtCh <- events.Event{ evtCh <- events.NewEvent().WithErrorEvent(events.ErrorEvent{
Type: events.ErrorType,
ErrorEvent: events.ErrorEvent{
Error: err, Error: err,
}, })
}
} }
// Validate executor configuration and documents // Validate executor configuration and documents

View File

@ -19,6 +19,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -122,12 +123,9 @@ func TestExecutorRun(t *testing.T) {
}, },
bundlePath: "testdata/executor_init", bundlePath: "testdata/executor_init",
expectedEvt: []events.Event{ expectedEvt: []events.Event{
{ events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitStart, Operation: events.ClusterctlInitStart,
}, }),
},
wrapError(errTmpFile), wrapError(errTmpFile),
}, },
}, },
@ -146,18 +144,12 @@ func TestExecutorRun(t *testing.T) {
}, },
bundlePath: "testdata/executor_init", bundlePath: "testdata/executor_init",
expectedEvt: []events.Event{ expectedEvt: []events.Event{
{ events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitStart, Operation: events.ClusterctlInitStart,
}, }),
}, events.NewEvent().WithClusterctlEvent(events.ClusterctlEvent{
{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitEnd, Operation: events.ClusterctlInitEnd,
}, }),
},
}, },
}, },
// TODO add move tests here // TODO add move tests here
@ -180,12 +172,18 @@ func TestExecutorRun(t *testing.T) {
go executor.Run(ch, ifc.RunOptions{DryRun: true}) go executor.Run(ch, ifc.RunOptions{DryRun: true})
var actualEvt []events.Event var actualEvt []events.Event
for evt := range ch { for evt := range ch {
// Skip timmestamp for comparison
evt.Timestamp = time.Time{}
if evt.Type == events.ClusterctlType { if evt.Type == events.ClusterctlType {
// Set message to empty string, so it's not compared // Set message to empty string, so it's not compared
evt.ClusterctlEvent.Message = "" evt.ClusterctlEvent.Message = ""
} }
actualEvt = append(actualEvt, evt) actualEvt = append(actualEvt, evt)
} }
for i := range tt.expectedEvt {
// Skip timmestamp for comparison
tt.expectedEvt[i].Timestamp = time.Time{}
}
assert.Equal(t, tt.expectedEvt, actualEvt) assert.Equal(t, tt.expectedEvt, actualEvt)
}) })
} }
@ -237,10 +235,7 @@ func executorDoc(t *testing.T, action string) document.Document {
} }
func wrapError(err error) events.Event { func wrapError(err error) events.Event {
return events.Event{ return events.NewEvent().WithErrorEvent(events.ErrorEvent{
Type: events.ErrorType,
ErrorEvent: events.ErrorEvent{
Error: err, Error: err,
}, })
}
} }

View File

@ -15,6 +15,8 @@
package events package events
import ( import (
"time"
applyevent "sigs.k8s.io/cli-utils/pkg/apply/event" applyevent "sigs.k8s.io/cli-utils/pkg/apply/event"
statuspollerevent "sigs.k8s.io/cli-utils/pkg/kstatus/polling/event" statuspollerevent "sigs.k8s.io/cli-utils/pkg/kstatus/polling/event"
) )
@ -40,6 +42,7 @@ const (
// Event holds all possible events that can be produced by airship // Event holds all possible events that can be produced by airship
type Event struct { type Event struct {
Type Type Type Type
Timestamp time.Time
ApplierEvent applyevent.Event ApplierEvent applyevent.Event
ErrorEvent ErrorEvent ErrorEvent ErrorEvent
StatusPollerEvent statuspollerevent.Event StatusPollerEvent statuspollerevent.Event
@ -47,11 +50,25 @@ type Event struct {
IsogenEvent IsogenEvent IsogenEvent IsogenEvent
} }
// NewEvent create new event with timestamp
func NewEvent() Event {
return Event{
Timestamp: time.Now(),
}
}
// ErrorEvent is produced when error is encountered // ErrorEvent is produced when error is encountered
type ErrorEvent struct { type ErrorEvent struct {
Error error Error error
} }
// WithErrorEvent sets type and actual error event
func (e Event) WithErrorEvent(event ErrorEvent) Event {
e.Type = ErrorType
e.ErrorEvent = event
return e
}
// ClusterctlOperation type // ClusterctlOperation type
type ClusterctlOperation int type ClusterctlOperation int
@ -72,6 +89,13 @@ type ClusterctlEvent struct {
Message string Message string
} }
// WithClusterctlEvent sets type and actual clusterctl event
func (e Event) WithClusterctlEvent(concreteEvent ClusterctlEvent) Event {
e.Type = ClusterctlType
e.ClusterctlEvent = concreteEvent
return e
}
// IsogenOperation type // IsogenOperation type
type IsogenOperation int type IsogenOperation int
@ -89,3 +113,10 @@ type IsogenEvent struct {
Operation IsogenOperation Operation IsogenOperation
Message string Message string
} }
// WithIsogenEvent sets type and actual isogen event
func (e Event) WithIsogenEvent(concreteEvent IsogenEvent) Event {
e.Type = IsogenType
e.IsogenEvent = concreteEvent
return e
}