-
Notifications
You must be signed in to change notification settings - Fork 80
/
Copy pathprinter.go
109 lines (101 loc) · 3.35 KB
/
printer.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
// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package json
import (
"encoding/json"
"fmt"
"strings"
"time"
"k8s.io/cli-runtime/pkg/genericiooptions"
"sigs.k8s.io/cli-utils/cmd/status/printers/printer"
"sigs.k8s.io/cli-utils/pkg/apply/event"
"sigs.k8s.io/cli-utils/pkg/common"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/collector"
pollevent "sigs.k8s.io/cli-utils/pkg/kstatus/polling/event"
"sigs.k8s.io/cli-utils/pkg/object"
"sigs.k8s.io/cli-utils/pkg/print/list"
jsonprinter "sigs.k8s.io/cli-utils/pkg/printers/json"
)
// Printer implements the Printer interface and outputs the resource
// status information as a list of events as they happen.
type Printer struct {
Formatter list.Formatter
IOStreams genericiooptions.IOStreams
Data *printer.PrintData
}
// NewPrinter returns a new instance of the eventPrinter.
func NewPrinter(ioStreams genericiooptions.IOStreams, printData *printer.PrintData) *Printer {
return &Printer{
Formatter: jsonprinter.NewFormatter(ioStreams, common.DryRunNone),
IOStreams: ioStreams,
Data: printData,
}
}
// Print takes an event channel and outputs the status events on the channel
// until the channel is closed. The provided cancelFunc is consulted on
// every event and is responsible for stopping the poller when appropriate.
// This function will block.
func (ep *Printer) Print(ch <-chan pollevent.Event, identifiers object.ObjMetadataSet,
cancelFunc collector.ObserverFunc) error {
coll := collector.NewResourceStatusCollector(identifiers)
// The actual work is done by the collector, which will invoke the
// callback on every event. In the callback we print the status
// information and call the cancelFunc which is responsible for
// stopping the poller at the correct time.
done := coll.ListenWithObserver(ch, collector.ObserverFunc(
func(statusCollector *collector.ResourceStatusCollector, e pollevent.Event) {
err := ep.printStatusEvent(e)
if err != nil {
panic(err)
}
cancelFunc(statusCollector, e)
}),
)
// Listen to the channel until it is closed.
var err error
for msg := range done {
err = msg.Err
}
return err
}
func (ep *Printer) printStatusEvent(se pollevent.Event) error {
switch se.Type {
case pollevent.ResourceUpdateEvent:
id := se.Resource.Identifier
var invName fmt.Stringer
var ok bool
if invName, ok = ep.Data.InvIDMap[id]; !ok {
return fmt.Errorf("%s: resource not found", id)
}
// filter out status that are not assigned
statusString := se.Resource.Status.String()
if _, ok := ep.Data.StatusSet[strings.ToLower(statusString)]; len(ep.Data.StatusSet) != 0 && !ok {
return nil
}
eventInfo := ep.createJSONObj(id)
eventInfo["inventory-name"] = invName
eventInfo["status"] = statusString
eventInfo["message"] = se.Resource.Message
b, err := json.Marshal(eventInfo)
if err != nil {
return err
}
_, err = fmt.Fprintf(ep.IOStreams.Out, "%s\n", string(b))
return err
case pollevent.ErrorEvent:
return ep.Formatter.FormatErrorEvent(event.ErrorEvent{
Err: se.Error,
})
}
return nil
}
func (ep *Printer) createJSONObj(id object.ObjMetadata) map[string]interface{} {
return map[string]interface{}{
"group": id.GroupKind.Group,
"kind": id.GroupKind.Kind,
"namespace": id.Namespace,
"name": id.Name,
"timestamp": time.Now().UTC().Format(time.RFC3339),
"type": "status",
}
}