package provider import ( "context" "github.com/docker/docker/api/types/container" "github.com/yusing/go-proxy/internal/docker" "github.com/yusing/go-proxy/internal/gperr" idlewatcher "github.com/yusing/go-proxy/internal/idlewatcher/types" "github.com/yusing/go-proxy/internal/watcher" ) type DockerProvider struct { client *docker.SharedClient watcher *watcher.DockerWatcher containerID string } var startOptions = container.StartOptions{} func NewDockerProvider(dockerHost, containerID string) (idlewatcher.Provider, error) { client, err := docker.NewClient(dockerHost) if err != nil { return nil, err } return &DockerProvider{ client: client, watcher: watcher.NewDockerWatcher(dockerHost), containerID: containerID, }, nil } func (p *DockerProvider) ContainerPause(ctx context.Context) error { return p.client.ContainerPause(ctx, p.containerID) } func (p *DockerProvider) ContainerUnpause(ctx context.Context) error { return p.client.ContainerUnpause(ctx, p.containerID) } func (p *DockerProvider) ContainerStart(ctx context.Context) error { return p.client.ContainerStart(ctx, p.containerID, startOptions) } func (p *DockerProvider) ContainerStop(ctx context.Context, signal idlewatcher.Signal, timeout int) error { return p.client.ContainerStop(ctx, p.containerID, container.StopOptions{ Signal: string(signal), Timeout: &timeout, }) } func (p *DockerProvider) ContainerKill(ctx context.Context, signal idlewatcher.Signal) error { return p.client.ContainerKill(ctx, p.containerID, string(signal)) } func (p *DockerProvider) ContainerStatus(ctx context.Context) (idlewatcher.ContainerStatus, error) { status, err := p.client.ContainerInspect(ctx, p.containerID) if err != nil { return idlewatcher.ContainerStatusError, err } switch status.State.Status { case "running": return idlewatcher.ContainerStatusRunning, nil case "exited", "dead", "restarting": return idlewatcher.ContainerStatusStopped, nil case "paused": return idlewatcher.ContainerStatusPaused, nil } return idlewatcher.ContainerStatusError, idlewatcher.ErrUnexpectedContainerStatus.Subject(status.State.Status) } func (p *DockerProvider) Watch(ctx context.Context) (eventCh <-chan watcher.Event, errCh <-chan gperr.Error) { return p.watcher.EventsWithOptions(ctx, watcher.DockerListOptions{ Filters: watcher.NewDockerFilter( watcher.DockerFilterContainer, watcher.DockerFilterContainerNameID(p.containerID), watcher.DockerFilterStart, watcher.DockerFilterStop, watcher.DockerFilterDie, watcher.DockerFilterKill, watcher.DockerFilterDestroy, watcher.DockerFilterPause, watcher.DockerFilterUnpause, ), }) } func (p *DockerProvider) Close() { p.client.Close() }