github.com/AbhinandanKurakure/podman/v3@v3.4.10/libpod/events.go (about) 1 package libpod 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 8 "github.com/containers/podman/v3/libpod/events" 9 "github.com/pkg/errors" 10 "github.com/sirupsen/logrus" 11 ) 12 13 // newEventer returns an eventer that can be used to read/write events 14 func (r *Runtime) newEventer() (events.Eventer, error) { 15 options := events.EventerOptions{ 16 EventerType: r.config.Engine.EventsLogger, 17 LogFilePath: r.config.Engine.EventsLogFilePath, 18 } 19 return events.NewEventer(options) 20 } 21 22 // newContainerEvent creates a new event based on a container 23 func (c *Container) newContainerEvent(status events.Status) { 24 e := events.NewEvent(status) 25 e.ID = c.ID() 26 e.Name = c.Name() 27 e.Image = c.config.RootfsImageName 28 e.Type = events.Container 29 30 e.Details = events.Details{ 31 ID: e.ID, 32 Attributes: c.Labels(), 33 } 34 35 if err := c.runtime.eventer.Write(e); err != nil { 36 logrus.Errorf("unable to write pod event: %q", err) 37 } 38 } 39 40 // newContainerExitedEvent creates a new event for a container's death 41 func (c *Container) newContainerExitedEvent(exitCode int32) { 42 e := events.NewEvent(events.Exited) 43 e.ID = c.ID() 44 e.Name = c.Name() 45 e.Image = c.config.RootfsImageName 46 e.Type = events.Container 47 e.ContainerExitCode = int(exitCode) 48 if err := c.runtime.eventer.Write(e); err != nil { 49 logrus.Errorf("unable to write container exited event: %q", err) 50 } 51 } 52 53 // newExecDiedEvent creates a new event for an exec session's death 54 func (c *Container) newExecDiedEvent(sessionID string, exitCode int) { 55 e := events.NewEvent(events.ExecDied) 56 e.ID = c.ID() 57 e.Name = c.Name() 58 e.Image = c.config.RootfsImageName 59 e.Type = events.Container 60 e.ContainerExitCode = exitCode 61 e.Attributes = make(map[string]string) 62 e.Attributes["execID"] = sessionID 63 if err := c.runtime.eventer.Write(e); err != nil { 64 logrus.Errorf("unable to write exec died event: %q", err) 65 } 66 } 67 68 // netNetworkEvent creates a new event based on a network connect/disconnect 69 func (c *Container) newNetworkEvent(status events.Status, netName string) { 70 e := events.NewEvent(status) 71 e.ID = c.ID() 72 e.Name = c.Name() 73 e.Type = events.Network 74 e.Network = netName 75 if err := c.runtime.eventer.Write(e); err != nil { 76 logrus.Errorf("unable to write pod event: %q", err) 77 } 78 } 79 80 // newPodEvent creates a new event for a libpod pod 81 func (p *Pod) newPodEvent(status events.Status) { 82 e := events.NewEvent(status) 83 e.ID = p.ID() 84 e.Name = p.Name() 85 e.Type = events.Pod 86 if err := p.runtime.eventer.Write(e); err != nil { 87 logrus.Errorf("unable to write pod event: %q", err) 88 } 89 } 90 91 // newSystemEvent creates a new event for libpod as a whole. 92 func (r *Runtime) newSystemEvent(status events.Status) { 93 e := events.NewEvent(status) 94 e.Type = events.System 95 96 if err := r.eventer.Write(e); err != nil { 97 logrus.Errorf("unable to write system event: %q", err) 98 } 99 } 100 101 // newVolumeEvent creates a new event for a libpod volume 102 func (v *Volume) newVolumeEvent(status events.Status) { 103 e := events.NewEvent(status) 104 e.Name = v.Name() 105 e.Type = events.Volume 106 if err := v.runtime.eventer.Write(e); err != nil { 107 logrus.Errorf("unable to write volume event: %q", err) 108 } 109 } 110 111 // Events is a wrapper function for everyone to begin tailing the events log 112 // with options 113 func (r *Runtime) Events(ctx context.Context, options events.ReadOptions) error { 114 eventer, err := r.newEventer() 115 if err != nil { 116 return err 117 } 118 return eventer.Read(ctx, options) 119 } 120 121 // GetEvents reads the event log and returns events based on input filters 122 func (r *Runtime) GetEvents(ctx context.Context, filters []string) ([]*events.Event, error) { 123 eventChannel := make(chan *events.Event) 124 options := events.ReadOptions{ 125 EventChannel: eventChannel, 126 Filters: filters, 127 FromStart: true, 128 Stream: false, 129 } 130 eventer, err := r.newEventer() 131 if err != nil { 132 return nil, err 133 } 134 135 logEvents := make([]*events.Event, 0, len(eventChannel)) 136 readLock := sync.Mutex{} 137 readLock.Lock() 138 go func() { 139 for e := range eventChannel { 140 logEvents = append(logEvents, e) 141 } 142 readLock.Unlock() 143 }() 144 145 readErr := eventer.Read(ctx, options) 146 readLock.Lock() // Wait for the events to be consumed. 147 return logEvents, readErr 148 } 149 150 // GetLastContainerEvent takes a container name or ID and an event status and returns 151 // the last occurrence of the container event 152 func (r *Runtime) GetLastContainerEvent(ctx context.Context, nameOrID string, containerEvent events.Status) (*events.Event, error) { 153 // check to make sure the event.Status is valid 154 if _, err := events.StringToStatus(containerEvent.String()); err != nil { 155 return nil, err 156 } 157 filters := []string{ 158 fmt.Sprintf("container=%s", nameOrID), 159 fmt.Sprintf("event=%s", containerEvent), 160 "type=container", 161 } 162 containerEvents, err := r.GetEvents(ctx, filters) 163 if err != nil { 164 return nil, err 165 } 166 if len(containerEvents) < 1 { 167 return nil, errors.Wrapf(events.ErrEventNotFound, "%s not found", containerEvent.String()) 168 } 169 // return the last element in the slice 170 return containerEvents[len(containerEvents)-1], nil 171 } 172 173 // GetExecDiedEvent takes a container name or ID, exec session ID, and returns 174 // that exec session's Died event (if it has already occurred). 175 func (r *Runtime) GetExecDiedEvent(ctx context.Context, nameOrID, execSessionID string) (*events.Event, error) { 176 filters := []string{ 177 fmt.Sprintf("container=%s", nameOrID), 178 "event=exec_died", 179 "type=container", 180 fmt.Sprintf("label=execID=%s", execSessionID), 181 } 182 183 containerEvents, err := r.GetEvents(ctx, filters) 184 if err != nil { 185 return nil, err 186 } 187 // There *should* only be one event maximum. 188 // But... just in case... let's not blow up if there's more than one. 189 if len(containerEvents) < 1 { 190 return nil, errors.Wrapf(events.ErrEventNotFound, "exec died event for session %s (container %s) not found", execSessionID, nameOrID) 191 } 192 return containerEvents[len(containerEvents)-1], nil 193 }