forked from AliyunContainerService/pouch
/
events.go
143 lines (122 loc) · 4.05 KB
/
events.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"sort"
"strings"
"time"
"github.com/alibaba/pouch/apis/filters"
"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/pkg/utils"
"github.com/spf13/cobra"
)
// eventsDescription is used to describe events command in detail and auto generate command doc.
var eventsDescription = "events cli tool is used to subscribe pouchd events." +
"We support filter parameter to filter some events that we care about or not."
// EventsCommand use to implement 'events' command.
type EventsCommand struct {
baseCommand
since string
until string
filter []string
}
// Init initialize events command.
func (e *EventsCommand) Init(c *Cli) {
e.cli = c
e.cmd = &cobra.Command{
Use: "events [OPTIONS]",
Short: "Get real time events from the daemon",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return e.runEvents()
},
Example: eventsExample(),
}
e.addFlags()
}
// addFlags adds flags for specific command.
func (e *EventsCommand) addFlags() {
flagSet := e.cmd.Flags()
flagSet.StringVarP(&e.since, "since", "s", "", "Show all events created since timestamp")
flagSet.StringVarP(&e.until, "until", "u", "", "Stream events until this timestamp")
flagSet.StringSliceVarP(&e.filter, "filter", "f", []string{}, "Filter output based on conditions provided")
}
// runEvents is the entry of events command.
func (e *EventsCommand) runEvents() error {
ctx := context.Background()
apiClient := e.cli.Client()
eventFilterArgs := filters.NewArgs()
// TODO: parse params
for _, f := range e.filter {
var err error
eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs)
if err != nil {
return err
}
}
responseBody, err := apiClient.Events(ctx, e.since, e.until, eventFilterArgs)
if err != nil {
return err
}
return streamEvents(responseBody, os.Stdout)
}
// streamEvents decodes prints the incoming events in the provided output.
func streamEvents(input io.Reader, output io.Writer) error {
return DecodeEvents(input, func(event types.EventsMessage, err error) error {
if err != nil {
return err
}
printOutput(event, output)
return nil
})
}
type eventProcessor func(event types.EventsMessage, err error) error
// printOutput prints all types of event information.
// Each output includes the event type, actor id, name and action.
// Actor attributes are printed at the end if the actor has any.
func printOutput(event types.EventsMessage, output io.Writer) {
if event.TimeNano != 0 {
fmt.Fprintf(output, "%s ", time.Unix(0, event.TimeNano).Format(utils.RFC3339NanoFixed))
} else if event.Time != 0 {
fmt.Fprintf(output, "%s ", time.Unix(event.Time, 0).Format(utils.RFC3339NanoFixed))
}
fmt.Fprintf(output, "%s %s %s", event.Type, event.Action, event.Actor.ID)
if len(event.Actor.Attributes) > 0 {
var attrs []string
var keys []string
for k := range event.Actor.Attributes {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
v := event.Actor.Attributes[k]
attrs = append(attrs, fmt.Sprintf("%s=%s", k, v))
}
fmt.Fprintf(output, " (%s)", strings.Join(attrs, ", "))
}
fmt.Fprint(output, "\n")
}
// DecodeEvents decodes event from input stream
func DecodeEvents(input io.Reader, ep eventProcessor) error {
dec := json.NewDecoder(input)
for {
var event types.EventsMessage
err := dec.Decode(&event)
if err != nil && err == io.EOF {
break
}
if procErr := ep(event, err); procErr != nil {
return procErr
}
}
return nil
}
func eventsExample() string {
return `$ pouch events -s "2018-08-10T10:52:05"
2018-08-10T10:53:15.071664386-04:00 volume create 9fff54f207615ccc5a29477f5ae2234c6b804ed8aad2f0dfc0dccb0cc69d4d12 (driver=local)
2018-08-10T10:53:15.091131306-04:00 container create f2b58eb6bc616d7a22bdb89de50b3f04e2c23134accdec1a9b9a7490d609d34c (image=registry.hub.docker.com/library/centos:latest, name=test)
2018-08-10T10:53:15.537704818-04:00 container start f2b58eb6bc616d7a22bdb89de50b3f04e2c23134accdec1a9b9a7490d609d34c (image=registry.hub.docker.com/library/centos:latest, name=test)`
}