Fix clusterctl, IsoGen executors to emit proper events

Change-Id: Ib69d9c85f7d27b83726f925d5a802c8e950c3a86
This commit is contained in:
Kostiantyn Kalynovskyi 2020-09-18 12:05:15 -05:00
parent 27e0ab455c
commit fc72884676
8 changed files with 73 additions and 2 deletions

View File

@ -0,0 +1,23 @@
/*
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 isogen
// ErrIsoGenNilBundle is returned when isogen executor is not provided with bundle
type ErrIsoGenNilBundle struct {
}
func (e ErrIsoGenNilBundle) Error() string {
return "Cannot build iso with empty bundle, no data source is available"
}

View File

@ -53,7 +53,10 @@ func RegisterExecutor(registry map[schema.GroupVersionKind]ifc.ExecutorFactory)
// NewExecutor creates instance of phase executor // NewExecutor creates instance of phase executor
func NewExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) { func NewExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) {
apiObj := &v1alpha1.ImageConfiguration{} apiObj := &v1alpha1.ImageConfiguration{
Container: &v1alpha1.Container{},
Builder: &v1alpha1.Builder{},
}
err := cfg.ExecutorDocument.ToAPIObject(apiObj, v1alpha1.Scheme) err := cfg.ExecutorDocument.ToAPIObject(apiObj, v1alpha1.Scheme)
if err != nil { if err != nil {
return nil, err return nil, err
@ -70,15 +73,23 @@ func NewExecutor(cfg ifc.ExecutorConfig) (ifc.Executor, error) {
func (c *Executor) Run(evtCh chan events.Event, opts ifc.RunOptions) { func (c *Executor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
defer close(evtCh) defer close(evtCh)
if c.ExecutorBundle == nil {
handleError(evtCh, ErrIsoGenNilBundle{})
return
}
evtCh <- events.Event{ evtCh <- events.Event{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{ IsogenEvent: events.IsogenEvent{
Operation: events.IsogenStart, Operation: events.IsogenStart,
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.Event{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{ IsogenEvent: events.IsogenEvent{
Operation: events.IsogenEnd, Operation: events.IsogenEnd,
}, },
@ -106,8 +117,10 @@ func (c *Executor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
} }
evtCh <- events.Event{ evtCh <- events.Event{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{ IsogenEvent: events.IsogenEvent{
Operation: events.IsogenValidation, Operation: events.IsogenValidation,
Message: "image is generated successfully, verifying artifacts",
}, },
} }
err = verifyArtifacts(c.imgConf) err = verifyArtifacts(c.imgConf)
@ -117,8 +130,10 @@ func (c *Executor) Run(evtCh chan events.Event, opts ifc.RunOptions) {
} }
evtCh <- events.Event{ evtCh <- events.Event{
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{ IsogenEvent: events.IsogenEvent{
Operation: events.IsogenEnd, Operation: events.IsogenEnd,
Message: "iso generation is complete and artifacts verified",
}, },
} }
} }

View File

@ -110,16 +110,19 @@ func TestExecutorRun(t *testing.T) {
}, },
expectedEvt: []events.Event{ expectedEvt: []events.Event{
{ {
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{ IsogenEvent: events.IsogenEvent{
Operation: events.IsogenStart, Operation: events.IsogenStart,
}, },
}, },
{ {
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{ IsogenEvent: events.IsogenEvent{
Operation: events.IsogenValidation, Operation: events.IsogenValidation,
}, },
}, },
{ {
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{ IsogenEvent: events.IsogenEvent{
Operation: events.IsogenEnd, Operation: events.IsogenEnd,
}, },
@ -138,6 +141,7 @@ func TestExecutorRun(t *testing.T) {
expectedEvt: []events.Event{ expectedEvt: []events.Event{
{ {
Type: events.IsogenType,
IsogenEvent: events.IsogenEvent{ IsogenEvent: events.IsogenEvent{
Operation: events.IsogenStart, Operation: events.IsogenStart,
}, },
@ -160,6 +164,10 @@ 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 {
if evt.Type == events.IsogenType {
// Set message to empty string, so it's not compared
evt.IsogenEvent.Message = ""
}
actualEvt = append(actualEvt, evt) actualEvt = append(actualEvt, evt)
} }
assert.Equal(t, tt.expectedEvt, actualEvt) assert.Equal(t, tt.expectedEvt, actualEvt)

View File

@ -88,8 +88,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.Event{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{ ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlMoveStart, Operation: events.ClusterctlMoveStart,
Message: "starting clusterctl move executor",
}, },
} }
ns := c.options.MoveOptions.Namespace ns := c.options.MoveOptions.Namespace
@ -115,16 +117,20 @@ func (c *ClusterctlExecutor) move(opts ifc.RunOptions, evtCh chan events.Event)
} }
evtCh <- events.Event{ evtCh <- events.Event{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{ ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlMoveEnd, Operation: events.ClusterctlMoveEnd,
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.Event{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{ ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitStart, Operation: events.ClusterctlInitStart,
Message: "starting clusterctl init executor",
}, },
} }
kubeConfigFile, cleanup, err := c.kubecfg.GetFile() kubeConfigFile, cleanup, err := c.kubecfg.GetFile()
@ -139,8 +145,10 @@ func (c *ClusterctlExecutor) init(opts ifc.RunOptions, evtCh chan events.Event)
// 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.Event{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{ ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitEnd, Operation: events.ClusterctlInitEnd,
Message: "clusterctl init dry-run completed successfully",
}, },
} }
return return
@ -151,8 +159,10 @@ func (c *ClusterctlExecutor) init(opts ifc.RunOptions, evtCh chan events.Event)
c.handleErr(err, evtCh) c.handleErr(err, evtCh)
} }
evtCh <- events.Event{ evtCh <- events.Event{
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{ ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitEnd, Operation: events.ClusterctlInitEnd,
Message: "clusterctl init completed successfully",
}, },
} }
} }

View File

@ -128,6 +128,7 @@ func TestExecutorRun(t *testing.T) {
bundlePath: "testdata/executor_init", bundlePath: "testdata/executor_init",
expectedEvt: []events.Event{ expectedEvt: []events.Event{
{ {
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{ ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitStart, Operation: events.ClusterctlInitStart,
}, },
@ -151,11 +152,13 @@ func TestExecutorRun(t *testing.T) {
bundlePath: "testdata/executor_init", bundlePath: "testdata/executor_init",
expectedEvt: []events.Event{ expectedEvt: []events.Event{
{ {
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{ ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitStart, Operation: events.ClusterctlInitStart,
}, },
}, },
{ {
Type: events.ClusterctlType,
ClusterctlEvent: events.ClusterctlEvent{ ClusterctlEvent: events.ClusterctlEvent{
Operation: events.ClusterctlInitEnd, Operation: events.ClusterctlInitEnd,
}, },
@ -185,6 +188,10 @@ 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 {
if evt.Type == events.ClusterctlType {
// Set message to empty string, so it's not compared
evt.ClusterctlEvent.Message = ""
}
actualEvt = append(actualEvt, evt) actualEvt = append(actualEvt, evt)
} }
assert.Equal(t, tt.expectedEvt, actualEvt) assert.Equal(t, tt.expectedEvt, actualEvt)

View File

@ -25,5 +25,5 @@ type ErrEventReceived struct {
func (e ErrEventReceived) Error() string { func (e ErrEventReceived) Error() string {
// TODO make printing more readable here // TODO make printing more readable here
return fmt.Sprintf("Applying of resources to kubernetes cluster has failed, errors are:\n%v", e.Errors) return fmt.Sprintf("Error events received on channel, errors are:\n%v", e.Errors)
} }

View File

@ -69,6 +69,7 @@ const (
// ClusterctlEvent is produced by clusterctl executor // ClusterctlEvent is produced by clusterctl executor
type ClusterctlEvent struct { type ClusterctlEvent struct {
Operation ClusterctlOperation Operation ClusterctlOperation
Message string
} }
// IsogenOperation type // IsogenOperation type
@ -86,4 +87,5 @@ const (
// IsogenEvent needs to to track events in isogen executor // IsogenEvent needs to to track events in isogen executor
type IsogenEvent struct { type IsogenEvent struct {
Operation IsogenOperation Operation IsogenOperation
Message string
} }

View File

@ -52,7 +52,13 @@ func (p *DefaultProcessor) Process(ch <-chan Event) error {
case ApplierType: case ApplierType:
p.processApplierEvent(e.ApplierEvent) p.processApplierEvent(e.ApplierEvent)
case ErrorType: case ErrorType:
log.Printf("Received error on event channel %v", e.ErrorEvent)
p.errors = append(p.errors, e.ErrorEvent.Error) p.errors = append(p.errors, e.ErrorEvent.Error)
case ClusterctlType, IsogenType:
// TODO each event needs to be interface that allows us to print it for example
// Stringer interface or AsYAML for further processing.
// For now we print the event object as is
log.Printf("Received event: %v", e)
case StatusPollerType: case StatusPollerType:
log.Fatalf("Processing for status poller events are not yet implemented") log.Fatalf("Processing for status poller events are not yet implemented")
case WaitType: case WaitType: