mirror of
https://github.com/containers/podman.git
synced 2025-08-06 11:32:07 +08:00
Add event logging to libpod, even display to podman
In lipod, we now log major events that occurr. These events can be displayed using the `podman events` command. Each event contains: * Type (container, image, volume, pod...) * Status (create, rm, stop, kill, ....) * Timestamp in RFC3339Nano format * Name (if applicable) * Image (if applicable) The format of the event and the varlink endpoint are to not be considered stable until cockpit has done its enablement. Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
264
libpod/events/events.go
Normal file
264
libpod/events/events.go
Normal file
@ -0,0 +1,264 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Event describes the attributes of a libpod event
|
||||
type Event struct {
|
||||
// ContainerExitCode is for storing the exit code of a container which can
|
||||
// be used for "internal" event notification
|
||||
ContainerExitCode int
|
||||
// ID can be for the container, image, volume, etc
|
||||
ID string
|
||||
// Image used where applicable
|
||||
Image string
|
||||
// Name where applicable
|
||||
Name string
|
||||
// Status describes the event that occurred
|
||||
Status Status
|
||||
// Time the event occurred
|
||||
Time time.Time
|
||||
// Type of event that occurred
|
||||
Type Type
|
||||
}
|
||||
|
||||
// Type of event that occurred (container, volume, image, pod, etc)
|
||||
type Type string
|
||||
|
||||
// Status describes the actual event action (stop, start, create, kill)
|
||||
type Status string
|
||||
|
||||
const (
|
||||
// If you add or subtract any values to the following lists, make sure you also update
|
||||
// the switch statements below and the enums for EventType or EventStatus in the
|
||||
// varlink description file.
|
||||
|
||||
// Container - event is related to containers
|
||||
Container Type = "container"
|
||||
// Image - event is related to images
|
||||
Image Type = "image"
|
||||
// Pod - event is related to pods
|
||||
Pod Type = "pod"
|
||||
// Volume - event is related to volumes
|
||||
Volume Type = "volume"
|
||||
|
||||
// Attach ...
|
||||
Attach Status = "attach"
|
||||
// Checkpoint ...
|
||||
Checkpoint Status = "checkpoint"
|
||||
// Cleanup ...
|
||||
Cleanup Status = "cleanup"
|
||||
// Commit ...
|
||||
Commit Status = "commit"
|
||||
// Create ...
|
||||
Create Status = "create"
|
||||
// Exec ...
|
||||
Exec Status = "exec"
|
||||
// Export ...
|
||||
Export Status = "export"
|
||||
// History ...
|
||||
History Status = "history"
|
||||
// Import ...
|
||||
Import Status = "import"
|
||||
// Init ...
|
||||
Init Status = "init"
|
||||
// Kill ...
|
||||
Kill Status = "kill"
|
||||
// LoadFromArchive ...
|
||||
LoadFromArchive Status = "status"
|
||||
// Mount ...
|
||||
Mount Status = "mount"
|
||||
// Pause ...
|
||||
Pause Status = "pause"
|
||||
// Prune ...
|
||||
Prune Status = "prune"
|
||||
// Pull ...
|
||||
Pull Status = "pull"
|
||||
// Push ...
|
||||
Push Status = "push"
|
||||
// Remove ...
|
||||
Remove Status = "remove"
|
||||
// Restore ...
|
||||
Restore Status = "restore"
|
||||
// Save ...
|
||||
Save Status = "save"
|
||||
// Start ...
|
||||
Start Status = "start"
|
||||
// Stop ...
|
||||
Stop Status = "stop"
|
||||
// Sync ...
|
||||
Sync Status = "sync"
|
||||
// Tag ...
|
||||
Tag Status = "tag"
|
||||
// Unmount ...
|
||||
Unmount Status = "unmount"
|
||||
// Unpause ...
|
||||
Unpause Status = "unpause"
|
||||
// Untag ...
|
||||
Untag Status = "untag"
|
||||
// Wait ...
|
||||
Wait Status = "wait"
|
||||
)
|
||||
|
||||
// EventFilter for filtering events
|
||||
type EventFilter func(*Event) bool
|
||||
|
||||
// NewEvent creates a event struct and populates with
|
||||
// the given status and time.
|
||||
func NewEvent(status Status) Event {
|
||||
return Event{
|
||||
Status: status,
|
||||
Time: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// Write will record the event to the given path
|
||||
func (e *Event) Write(path string) error {
|
||||
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
eventJSONString, err := e.ToJSONString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.WriteString(fmt.Sprintf("%s\n", eventJSONString)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Recycle checks if the event log has reach a limit and if so
|
||||
// renames the current log and starts a new one. The remove bool
|
||||
// indicates the old log file should be deleted.
|
||||
func (e *Event) Recycle(path string, remove bool) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// ToJSONString returns the event as a json'ified string
|
||||
func (e *Event) ToJSONString() (string, error) {
|
||||
b, err := json.Marshal(e)
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
// ToHumanReadable returns human readable event as a formatted string
|
||||
func (e *Event) ToHumanReadable() string {
|
||||
var humanFormat string
|
||||
switch e.Type {
|
||||
case Container, Pod:
|
||||
humanFormat = fmt.Sprintf("%s %s %s %s (image=%s, name=%s)", e.Time, e.Type, e.Status, e.ID, e.Image, e.Name)
|
||||
case Image:
|
||||
humanFormat = fmt.Sprintf("%s %s %s %s %s", e.Time, e.Type, e.Status, e.ID, e.Name)
|
||||
case Volume:
|
||||
humanFormat = fmt.Sprintf("%s %s %s %s", e.Time, e.Type, e.Status, e.Name)
|
||||
}
|
||||
return humanFormat
|
||||
}
|
||||
|
||||
// NewEventFromString takes stringified json and converts
|
||||
// it to an event
|
||||
func NewEventFromString(event string) (*Event, error) {
|
||||
e := Event{}
|
||||
if err := json.Unmarshal([]byte(event), &e); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &e, nil
|
||||
|
||||
}
|
||||
|
||||
// ToString converts a Type to a string
|
||||
func (t Type) String() string {
|
||||
return string(t)
|
||||
}
|
||||
|
||||
// ToString converts a status to a string
|
||||
func (s Status) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// StringToType converts string to an EventType
|
||||
func StringToType(name string) (Type, error) {
|
||||
switch name {
|
||||
case Container.String():
|
||||
return Container, nil
|
||||
case Image.String():
|
||||
return Image, nil
|
||||
case Pod.String():
|
||||
return Pod, nil
|
||||
case Volume.String():
|
||||
return Volume, nil
|
||||
}
|
||||
return "", errors.Errorf("unknown event type %s", name)
|
||||
}
|
||||
|
||||
// StringToStatus converts a string to an Event Status
|
||||
// TODO if we add more events, we might consider a go-generator to
|
||||
// create the switch statement
|
||||
func StringToStatus(name string) (Status, error) {
|
||||
switch name {
|
||||
case Attach.String():
|
||||
return Attach, nil
|
||||
case Checkpoint.String():
|
||||
return Checkpoint, nil
|
||||
case Restore.String():
|
||||
return Restore, nil
|
||||
case Cleanup.String():
|
||||
return Cleanup, nil
|
||||
case Commit.String():
|
||||
return Commit, nil
|
||||
case Create.String():
|
||||
return Create, nil
|
||||
case Exec.String():
|
||||
return Exec, nil
|
||||
case Export.String():
|
||||
return Export, nil
|
||||
case History.String():
|
||||
return History, nil
|
||||
case Import.String():
|
||||
return Import, nil
|
||||
case Init.String():
|
||||
return Init, nil
|
||||
case Kill.String():
|
||||
return Kill, nil
|
||||
case LoadFromArchive.String():
|
||||
return LoadFromArchive, nil
|
||||
case Mount.String():
|
||||
return Mount, nil
|
||||
case Pause.String():
|
||||
return Pause, nil
|
||||
case Prune.String():
|
||||
return Prune, nil
|
||||
case Pull.String():
|
||||
return Pull, nil
|
||||
case Push.String():
|
||||
return Push, nil
|
||||
case Remove.String():
|
||||
return Remove, nil
|
||||
case Save.String():
|
||||
return Save, nil
|
||||
case Start.String():
|
||||
return Start, nil
|
||||
case Stop.String():
|
||||
return Stop, nil
|
||||
case Sync.String():
|
||||
return Sync, nil
|
||||
case Tag.String():
|
||||
return Tag, nil
|
||||
case Unmount.String():
|
||||
return Unmount, nil
|
||||
case Unpause.String():
|
||||
return Unpause, nil
|
||||
case Untag.String():
|
||||
return Untag, nil
|
||||
case Wait.String():
|
||||
return Wait, nil
|
||||
}
|
||||
return "", errors.Errorf("unknown event status %s", name)
|
||||
}
|
Reference in New Issue
Block a user