mirror of
https://github.com/containers/podman
synced 2024-10-20 01:03:51 +00:00
06dd9136a2
Numerous issues remain, especially in tests/e2e. Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
110 lines
2.5 KiB
Go
110 lines
2.5 KiB
Go
package events
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/containers/podman/v4/pkg/util"
|
|
"github.com/containers/storage/pkg/lockfile"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// EventLogFile is the structure for event writing to a logfile. It contains the eventer
|
|
// options and the event itself. Methods for reading and writing are also defined from it.
|
|
type EventLogFile struct {
|
|
options EventerOptions
|
|
}
|
|
|
|
// Writes to the log file
|
|
func (e EventLogFile) Write(ee Event) error {
|
|
// We need to lock events file
|
|
lock, err := lockfile.GetLockfile(e.options.LogFilePath + ".lock")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
f, err := os.OpenFile(e.options.LogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0700)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
eventJSONString, err := ee.ToJSONString()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := f.WriteString(fmt.Sprintf("%s\n", eventJSONString)); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Reads from the log file
|
|
func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error {
|
|
defer close(options.EventChannel)
|
|
filterMap, err := generateEventFilters(options.Filters, options.Since, options.Until)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "failed to parse event filters")
|
|
}
|
|
t, err := e.getTail(options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(options.Until) > 0 {
|
|
untilTime, err := util.ParseInputTime(options.Until, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
go func() {
|
|
time.Sleep(time.Until(untilTime))
|
|
if err := t.Stop(); err != nil {
|
|
logrus.Errorf("Stopping logger: %v", err)
|
|
}
|
|
}()
|
|
}
|
|
funcDone := make(chan bool)
|
|
copy := true
|
|
go func() {
|
|
select {
|
|
case <-funcDone:
|
|
// Do nothing
|
|
case <-ctx.Done():
|
|
copy = false
|
|
t.Kill(errors.New("hangup by client"))
|
|
}
|
|
}()
|
|
for line := range t.Lines {
|
|
select {
|
|
case <-ctx.Done():
|
|
// the consumer has cancelled
|
|
return nil
|
|
default:
|
|
// fallthrough
|
|
}
|
|
|
|
event, err := newEventFromJSONString(line.Text)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
switch event.Type {
|
|
case Image, Volume, Pod, System, Container, Network:
|
|
// no-op
|
|
default:
|
|
return errors.Errorf("event type %s is not valid in %s", event.Type.String(), e.options.LogFilePath)
|
|
}
|
|
if copy && applyFilters(event, filterMap) {
|
|
options.EventChannel <- event
|
|
}
|
|
}
|
|
funcDone <- true
|
|
return nil
|
|
}
|
|
|
|
// String returns a string representation of the logger
|
|
func (e EventLogFile) String() string {
|
|
return LogFile.String()
|
|
}
|