func (m *Monitor) createContainerDestroyedEvent(msg events.Message) *model.ContainerEvent {
	return &model.ContainerEvent{
		EventBase: model.EventBase{
			EventType:        model.ContainerDestroyedEventType,
			EventMonitorName: m.Name,
		},
		ContainerID:   msg.ID,
		Image:         msg.Actor.Attributes["image"],
		ContainerName: msg.Actor.Attributes["name"],
	}
}
createContainerDestroyedEvent - Create a container "destroyed" event
package docker
import (
	"context"
	"fmt"
	"strings"
	"sync"
	"time"
	godocker "docker.io/go-docker"
	"docker.io/go-docker/api/types"
	"docker.io/go-docker/api/types/events"
	"docker.io/go-docker/api/types/filters"
	"github.com/Gui774ume/ebpf"
	"github.com/sirupsen/logrus"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"github.com/Gui774ume/network-security-probe/pkg/config"
	"github.com/Gui774ume/network-security-probe/pkg/model"
	"github.com/Gui774ume/network-security-probe/pkg/utils"
)
var (
	dockerLogger = logrus.WithField("package", "docker")
)
var DMonitor Monitor = Monitor{
	Name: model.DockerMonitor,
}
type Monitor struct {
	Name                  model.MonitorName
	Nsp                   model.NSPInterface
	k8sClientSet          *kubernetes.Clientset
	wg                    *sync.WaitGroup
	config                *config.NSPConfig
	collection            *ebpf.Collection
	Client                *godocker.Client
	EventsContext         context.Context
	EventsCancel          context.CancelFunc
	eventStreamRetries    int
	eventStreamMaxRetries int
}
func (m *Monitor) GetName() model.MonitorName {
	return m.Name
}
func (m *Monitor) Init(nsp model.NSPInterface) error {
	m.eventStreamMaxRetries = 5
	m.Nsp = nsp
	m.wg = nsp.GetWaitGroup()
	m.config = nsp.GetConfig()
	m.collection = nsp.GetCollection()
	var err error
	m.Client, err = godocker.NewEnvClient()
	if err != nil {
		return err
	}
	m.EventsContext, m.EventsCancel = context.WithCancel(context.Background())
	m.k8sClientSet, err = kubernetes.NewForConfig(nsp.GetKubeConfig())
	if err != nil {
		return err
	}
	return nil
}
func (m *Monitor) Start() error {
	go m.listenForDockerEvents()
	containers, err := m.Client.ContainerList(context.Background(), types.ContainerListOptions{})
	if err != nil {
		return err
	}
	dockerLogger.Debugf("%v monitor is running", m.GetName())
	for _, c := range containers {
		cdata, err := m.createContainerEventFromContainerID(c.ID)
		if err != nil {
			continue
		}
		cdata.Timestamp = time.Now()
		cdata.EventType = model.ContainerRunningEventType
		if err := m.filterAndDispatchEvent(cdata); err != nil {
			dockerLogger.Errorf("Docker dispatch error: %v", err)
		}
	}
	return nil
}
func (m *Monitor) listenForDockerEvents() {
	m.wg.Add(1)
	filter := filters.NewArgs()
	filter.Add("type", events.NetworkEventType)
	filter.Add("type", events.ContainerEventType)
	msgs, errs := m.Client.Events(m.EventsContext, types.EventsOptions{
		Filters: filter,
	})
	for {
		select {
		case err := <-errs:
			if err == context.Canceled {
				m.wg.Done()
				return
			}
			dockerLogger.Errorf("Docker monitor: %v", err)
			m.eventStreamRetries++
			if m.eventStreamRetries >= m.eventStreamMaxRetries {
				dockerLogger.Errorf("Docker event monitor max retries reached")
				m.wg.Done()
				return
			}
			m.wg.Done()
			m.listenForDockerEvents()
			return
		case msg := <-msgs:
			m.eventStreamRetries = 0
			switch msg.Type {
			case events.ContainerEventType:
				if err := m.handleContainerEvent(msg); err != nil {
					dockerLogger.Warnf("Docker monitor error: %v", err)
				}
			case events.NetworkEventType:
				if err := m.handleNetworkEvent(msg); err != nil {
					dockerLogger.Warnf("Docker monitor error: %v", err)
				}
			default:
				dockerLogger.Warnf("unknown Docker event type: %v", msg.Type)
			}
		}
	}
}
func (m *Monitor) handleContainerEvent(msg events.Message) error {
	var cmd string
	var args []string
	probeEventType := model.UnknownEventType
	switch msg.Action {
	case "create":
		probeEventType = model.ContainerCreatedEventType
	case "attach":
		probeEventType = model.ContainerAttachEventType
	case "start":
		probeEventType = model.ContainerRunningEventType
	case "destroy":
		probeEventType = model.ContainerDestroyedEventType
	case "die", "kill", "stop":
		probeEventType = model.ContainerExitedEventType
	default:
		splittedAction := strings.Split(msg.Action, ": ")
		switch splittedAction[0] {
		case "exec_start":
			probeEventType = model.ContainerExecEventType
			splittedCmd := strings.Split(splittedAction[1], " ")
			cmd = splittedCmd[0]
			args = splittedCmd[1:]
		default:
			return nil
		}
	}
	var cdata *model.ContainerEvent
	var err error
	switch probeEventType {
	case model.ContainerDestroyedEventType, model.ContainerExitedEventType:
		cdata = m.createContainerDestroyedEvent(msg)
	default:
		cdata, err = m.createContainerEventFromContainerID(msg.ID)
		if err != nil {
			return err
		}
	}
	cdata.EventType = probeEventType
	if probeEventType == model.ContainerExecEventType {
		cdata.CommandPath = cmd
		cdata.CommandArgs = args
	}
	cdata.Timestamp = time.Unix(0, msg.TimeNano)
	return m.filterAndDispatchEvent(cdata)
}
func (m *Monitor) handleNetworkEvent(msg events.Message) error {
	probeEventType := model.UnknownEventType
	switch msg.Action {
	case "connect":
		probeEventType = model.ContainerConnectEventType
	case "disconnect":
		probeEventType = model.ContainerDisconnectEventType
	}
	cdata, err := m.createContainerEventFromContainerID(msg.Actor.Attributes["container"])
	if err != nil {
		return err
	}
	cdata.EventType = probeEventType
	cdata.Timestamp = time.Unix(0, msg.TimeNano)
	return m.filterAndDispatchEvent(cdata)
}
func (m *Monitor) Stop() error {
	m.EventsCancel()
	return nil
}
func (m *Monitor) filterAndDispatchEvent(event *model.ContainerEvent) error {
	m.Nsp.DispatchEvent(event)
	return nil
}