podman

Форк
0
/
events.go 
248 строк · 7.4 Кб
1
//go:build !remote
2

3
package libpod
4

5
import (
6
	"context"
7
	"fmt"
8
	"path/filepath"
9
	"sync"
10

11
	"github.com/containers/podman/v5/libpod/events"
12
	"github.com/sirupsen/logrus"
13
)
14

15
// newEventer returns an eventer that can be used to read/write events
16
func (r *Runtime) newEventer() (events.Eventer, error) {
17
	if r.config.Engine.EventsLogFilePath == "" {
18
		// default, use path under tmpdir when none was explicitly set by the user
19
		r.config.Engine.EventsLogFilePath = filepath.Join(r.config.Engine.TmpDir, "events", "events.log")
20
	}
21
	options := events.EventerOptions{
22
		EventerType:    r.config.Engine.EventsLogger,
23
		LogFilePath:    r.config.Engine.EventsLogFilePath,
24
		LogFileMaxSize: r.config.Engine.EventsLogMaxSize(),
25
	}
26
	return events.NewEventer(options)
27
}
28

29
// newContainerEvent creates a new event based on a container
30
func (c *Container) newContainerEvent(status events.Status) {
31
	if err := c.newContainerEventWithInspectData(status, "", false); err != nil {
32
		logrus.Errorf("Unable to write container event: %v", err)
33
	}
34
}
35

36
// newContainerHealthCheckEvent creates a new healthcheck event with the given status
37
func (c *Container) newContainerHealthCheckEvent(healthStatus string) {
38
	if err := c.newContainerEventWithInspectData(events.HealthStatus, healthStatus, false); err != nil {
39
		logrus.Errorf("Unable to write container event: %v", err)
40
	}
41
}
42

43
// newContainerEventWithInspectData creates a new event and sets the
44
// ContainerInspectData field if inspectData is set.
45
func (c *Container) newContainerEventWithInspectData(status events.Status, healthStatus string, inspectData bool) error {
46
	e := events.NewEvent(status)
47
	e.ID = c.ID()
48
	e.Name = c.Name()
49
	e.Image = c.config.RootfsImageName
50
	e.Type = events.Container
51
	e.HealthStatus = healthStatus
52

53
	e.Details = events.Details{
54
		PodID:      c.PodID(),
55
		Attributes: c.Labels(),
56
	}
57

58
	if inspectData {
59
		err := func() error {
60
			data, err := c.inspectLocked(true)
61
			if err != nil {
62
				return err
63
			}
64
			rawData, err := json.Marshal(data)
65
			if err != nil {
66
				return err
67
			}
68
			e.Details.ContainerInspectData = string(rawData)
69
			return nil
70
		}()
71
		if err != nil {
72
			return fmt.Errorf("adding inspect data to container-create event: %v", err)
73
		}
74
	}
75

76
	if status == events.Remove {
77
		exitCode, err := c.runtime.state.GetContainerExitCode(c.ID())
78
		if err == nil {
79
			intExitCode := int(exitCode)
80
			e.ContainerExitCode = &intExitCode
81
		}
82
	}
83

84
	return c.runtime.eventer.Write(e)
85
}
86

87
// newContainerExitedEvent creates a new event for a container's death
88
func (c *Container) newContainerExitedEvent(exitCode int32) {
89
	e := events.NewEvent(events.Exited)
90
	e.ID = c.ID()
91
	e.Name = c.Name()
92
	e.Image = c.config.RootfsImageName
93
	e.Type = events.Container
94
	e.PodID = c.PodID()
95
	intExitCode := int(exitCode)
96
	e.ContainerExitCode = &intExitCode
97

98
	e.Details = events.Details{
99
		Attributes: c.Labels(),
100
	}
101

102
	if err := c.runtime.eventer.Write(e); err != nil {
103
		logrus.Errorf("Unable to write container exited event: %q", err)
104
	}
105
}
106

107
// newExecDiedEvent creates a new event for an exec session's death
108
func (c *Container) newExecDiedEvent(sessionID string, exitCode int) {
109
	e := events.NewEvent(events.ExecDied)
110
	e.ID = c.ID()
111
	e.Name = c.Name()
112
	e.Image = c.config.RootfsImageName
113
	e.Type = events.Container
114
	intExitCode := exitCode
115
	e.ContainerExitCode = &intExitCode
116
	e.Attributes = make(map[string]string)
117
	e.Attributes["execID"] = sessionID
118

119
	e.Details = events.Details{
120
		Attributes: c.Labels(),
121
	}
122

123
	if err := c.runtime.eventer.Write(e); err != nil {
124
		logrus.Errorf("Unable to write exec died event: %q", err)
125
	}
126
}
127

128
// newNetworkEvent creates a new event based on a network connect/disconnect
129
func (c *Container) newNetworkEvent(status events.Status, netName string) {
130
	e := events.NewEvent(status)
131
	e.ID = c.ID()
132
	e.Name = c.Name()
133
	e.Type = events.Network
134
	e.Network = netName
135
	if err := c.runtime.eventer.Write(e); err != nil {
136
		logrus.Errorf("Unable to write pod event: %q", err)
137
	}
138
}
139

140
// newPodEvent creates a new event for a libpod pod
141
func (p *Pod) newPodEvent(status events.Status) {
142
	e := events.NewEvent(status)
143
	e.ID = p.ID()
144
	e.Name = p.Name()
145
	e.Type = events.Pod
146
	if err := p.runtime.eventer.Write(e); err != nil {
147
		logrus.Errorf("Unable to write pod event: %q", err)
148
	}
149
}
150

151
// NewSystemEvent creates a new event for libpod as a whole.
152
func (r *Runtime) NewSystemEvent(status events.Status) {
153
	e := events.NewEvent(status)
154
	e.Type = events.System
155

156
	if err := r.eventer.Write(e); err != nil {
157
		logrus.Errorf("Unable to write system event: %q", err)
158
	}
159
}
160

161
// newVolumeEvent creates a new event for a libpod volume
162
func (v *Volume) newVolumeEvent(status events.Status) {
163
	e := events.NewEvent(status)
164
	e.Name = v.Name()
165
	e.Type = events.Volume
166
	if err := v.runtime.eventer.Write(e); err != nil {
167
		logrus.Errorf("Unable to write volume event: %q", err)
168
	}
169
}
170

171
// Events is a wrapper function for everyone to begin tailing the events log
172
// with options
173
func (r *Runtime) Events(ctx context.Context, options events.ReadOptions) error {
174
	return r.eventer.Read(ctx, options)
175
}
176

177
// GetEvents reads the event log and returns events based on input filters
178
func (r *Runtime) GetEvents(ctx context.Context, filters []string) ([]*events.Event, error) {
179
	eventChannel := make(chan *events.Event)
180
	options := events.ReadOptions{
181
		EventChannel: eventChannel,
182
		Filters:      filters,
183
		FromStart:    true,
184
		Stream:       false,
185
	}
186

187
	logEvents := make([]*events.Event, 0, len(eventChannel))
188
	readLock := sync.Mutex{}
189
	readLock.Lock()
190
	go func() {
191
		for e := range eventChannel {
192
			logEvents = append(logEvents, e)
193
		}
194
		readLock.Unlock()
195
	}()
196

197
	readErr := r.eventer.Read(ctx, options)
198
	readLock.Lock() // Wait for the events to be consumed.
199
	return logEvents, readErr
200
}
201

202
// GetLastContainerEvent takes a container name or ID and an event status and returns
203
// the last occurrence of the container event
204
func (r *Runtime) GetLastContainerEvent(ctx context.Context, nameOrID string, containerEvent events.Status) (*events.Event, error) {
205
	// FIXME: events should be read in reverse order!
206
	// https://github.com/containers/podman/issues/14579
207

208
	// check to make sure the event.Status is valid
209
	if _, err := events.StringToStatus(containerEvent.String()); err != nil {
210
		return nil, err
211
	}
212
	filters := []string{
213
		fmt.Sprintf("container=%s", nameOrID),
214
		fmt.Sprintf("event=%s", containerEvent),
215
		"type=container",
216
	}
217
	containerEvents, err := r.GetEvents(ctx, filters)
218
	if err != nil {
219
		return nil, err
220
	}
221
	if len(containerEvents) < 1 {
222
		return nil, fmt.Errorf("%s not found: %w", containerEvent.String(), events.ErrEventNotFound)
223
	}
224
	// return the last element in the slice
225
	return containerEvents[len(containerEvents)-1], nil
226
}
227

228
// GetExecDiedEvent takes a container name or ID, exec session ID, and returns
229
// that exec session's Died event (if it has already occurred).
230
func (r *Runtime) GetExecDiedEvent(ctx context.Context, nameOrID, execSessionID string) (*events.Event, error) {
231
	filters := []string{
232
		fmt.Sprintf("container=%s", nameOrID),
233
		"event=exec_died",
234
		"type=container",
235
		fmt.Sprintf("label=execID=%s", execSessionID),
236
	}
237

238
	containerEvents, err := r.GetEvents(ctx, filters)
239
	if err != nil {
240
		return nil, err
241
	}
242
	// There *should* only be one event maximum.
243
	// But... just in case... let's not blow up if there's more than one.
244
	if len(containerEvents) < 1 {
245
		return nil, fmt.Errorf("exec died event for session %s (container %s) not found: %w", execSessionID, nameOrID, events.ErrEventNotFound)
246
	}
247
	return containerEvents[len(containerEvents)-1], nil
248
}
249

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.