package events import ( "context" "errors" "fmt" "time" "github.com/containerd/containerd" eventtypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/containers" ctrevents "github.com/containerd/containerd/events" typeurl "github.com/containerd/typeurl/v2" criruntime "k8s.io/cri-api/pkg/apis/runtime/v1" devicecontainers "edge-infra.dev/pkg/sds/devices/agent/containers" "edge-infra.dev/pkg/sds/devices/class" "edge-infra.dev/pkg/sds/devices/logger" ) // ContainerEventConstructor returns a constructor function that instantiates a new device container event for given container event func ContainerEventConstructor(containers map[string]*containers.Container, ctrClient *containerd.Client, runtimeClient criruntime.RuntimeServiceClient) func(ctx context.Context, ctrEvent *ctrevents.Envelope) (DeviceEvent, error) { return func(ctx context.Context, ctrEvent *ctrevents.Envelope) (DeviceEvent, error) { event, err := typeurl.UnmarshalAny(ctrEvent.Event) if err != nil { return nil, fmt.Errorf("error reading container event: %w", err) } log := logger.FromContext(ctx) if createEvent, ok := event.(*eventtypes.ContainerCreate); ok { log.Debug("container was created", "containerID", createEvent.ID) ctr, err := devicecontainers.FetchContainer(ctx, ctrClient, runtimeClient, createEvent.ID) if err != nil { log.Error("could not fetch container", "containerID", createEvent.ID, "error", err) return nil, nil } if ctr == nil { return nil, nil } containers[ctr.ID] = ctr event, err := NewContainerEvent(ctr) if err != nil { return nil, fmt.Errorf("error generating container event: %w", err) } return event, nil } if deleteEvent, ok := event.(*eventtypes.ContainerDelete); ok { log.Debug("container was deleted", "containerID", deleteEvent.ID) delete(containers, deleteEvent.ID) } return nil, nil } } // NewContainerEvent returns a new device event from created container func NewContainerEvent(container *containers.Container) (DeviceEvent, error) { if container == nil { return nil, errors.New("container cannot be nil") } container.Labels[class.DefaultClass] = requested return &containerEvent{ event: &event{ containers: map[string]*containers.Container{ container.ID: container, }, postHookFn: func(context.Context) {}, timestamp: time.Now(), }, }, nil }