Docker template generator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

container_monitor.go 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/docker/docker/api/types"
  6. "github.com/docker/docker/api/types/filters"
  7. "github.com/docker/docker/client"
  8. "time"
  9. )
  10. type ContainerMonitor struct {
  11. newContainers chan<- Container
  12. goneContainerNames chan<- string
  13. client *client.Client
  14. expiryTimes map[string]time.Time
  15. deletionTime time.Duration
  16. nextExpiry time.Time
  17. expiryTimer *time.Timer
  18. }
  19. func NewContainerMonitor(client *client.Client, newContainerChannel chan<- Container, goneContainerChannel chan<- string) *ContainerMonitor {
  20. timer := time.NewTimer(time.Hour)
  21. timer.Stop()
  22. return &ContainerMonitor{
  23. newContainers: newContainerChannel,
  24. goneContainerNames: goneContainerChannel,
  25. client: client,
  26. expiryTimes: make(map[string]time.Time),
  27. deletionTime: 10 * time.Second,
  28. expiryTimer: timer,
  29. nextExpiry: time.Now(),
  30. }
  31. }
  32. func (c *ContainerMonitor) Monitor() {
  33. args := filters.NewArgs()
  34. args.Add("type", "container")
  35. args.Add("event", "create")
  36. args.Add("event", "destroy")
  37. eventsChan, errChan := c.client.Events(context.Background(), types.EventsOptions{Filters: args})
  38. c.publishExistingContainers()
  39. for {
  40. select {
  41. case event := <-eventsChan:
  42. if event.Action == "create" {
  43. c.publishNewContainer(event.Actor.ID)
  44. } else {
  45. c.scheduleExpiry(event.Actor.Attributes["name"])
  46. }
  47. case <-c.expiryTimer.C:
  48. c.publishExpiredContainers()
  49. case err := <-errChan:
  50. panic(err)
  51. }
  52. }
  53. }
  54. func (c *ContainerMonitor) publishExistingContainers() {
  55. containers, err := c.client.ContainerList(context.Background(), types.ContainerListOptions{})
  56. if err != nil {
  57. panic(err)
  58. }
  59. for _, container := range containers {
  60. c.newContainers <- Container{
  61. Id: container.ID,
  62. Name: container.Names[0][1:],
  63. Labels: container.Labels,
  64. }
  65. }
  66. }
  67. func (c *ContainerMonitor) publishNewContainer(id string) {
  68. container, err := c.client.ContainerInspect(context.Background(), id)
  69. if err != nil {
  70. panic(err)
  71. }
  72. c.newContainers <- Container{
  73. Id: container.ID,
  74. Name: container.Name[1:],
  75. Labels: container.Config.Labels,
  76. }
  77. delete(c.expiryTimes, container.Name[1:])
  78. }
  79. func (c *ContainerMonitor) scheduleExpiry(name string) {
  80. now := time.Now()
  81. expiryTime := now.Add(c.deletionTime)
  82. c.expiryTimes[name] = expiryTime
  83. fmt.Printf("Scheduling expiry timer for %s\n", name)
  84. if c.nextExpiry.Before(now) || c.nextExpiry.After(expiryTime) {
  85. fmt.Printf("Starting expiry timer with default duration\n")
  86. c.expiryTimer.Reset(c.deletionTime + 1*time.Second)
  87. c.nextExpiry = expiryTime
  88. }
  89. }
  90. func (c *ContainerMonitor) publishExpiredContainers() {
  91. now := time.Now()
  92. next := 0 * time.Second
  93. for name, expiryTime := range c.expiryTimes {
  94. if expiryTime.Before(now) {
  95. fmt.Printf("Expiring %s\n", name)
  96. delete(c.expiryTimes, name)
  97. c.goneContainerNames <- name
  98. } else if next == 0 || expiryTime.Sub(now) < next {
  99. next = expiryTime.Sub(now)
  100. }
  101. }
  102. if next > 0 {
  103. fmt.Printf("Starting expiry timer with duration %s\n", next)
  104. c.expiryTimer.Reset(next + 1*time.Second)
  105. c.nextExpiry = now.Add(next)
  106. }
  107. }