-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcontainer.go
More file actions
156 lines (129 loc) · 4.03 KB
/
container.go
File metadata and controls
156 lines (129 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package main
import (
"context"
"fmt"
"os"
"os/signal"
"strconv"
"syscall"
"time"
typesContainer "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/client"
"ldddns.arnested.dk/internal/container"
"ldddns.arnested.dk/internal/hostname"
"ldddns.arnested.dk/internal/log"
)
//nolint:cyclop
func handleContainer(
ctx context.Context,
docker *client.Client,
containerID string,
egs *entryGroups,
status string,
config Config,
) error {
entryGroup, commit, err := egs.get(containerID)
defer commit()
if err != nil {
// The error from egs.get() already includes containerID and is descriptive
return fmt.Errorf("cannot get Avahi entry group for container %s: %w", containerID, err)
}
log.Logf(log.PriDebug, "Checking if Avahi entry group for container %s is empty (before potential reset)", containerID)
empty, err := entryGroup.IsEmpty()
if err != nil {
return fmt.Errorf("error checking whether Avahi entry group for container %s is empty: %w", containerID, err)
}
log.Logf(log.PriDebug, "Result of IsEmpty check for Avahi entry group for container %s: %t", containerID, empty)
if !empty {
log.Logf(log.PriDebug, "Attempting to reset Avahi entry group for container %s because it was not empty", containerID)
err := entryGroup.Reset()
if err != nil {
return fmt.Errorf("error resetting Avahi entry group for container %s: %w", containerID, err)
}
log.Logf(log.PriDebug, "Successfully reset Avahi entry group for container %s", containerID)
}
if status == "die" || status == "kill" || status == "pause" {
return nil
}
containerJSON, err := docker.ContainerInspect(ctx, containerID)
if err != nil {
return fmt.Errorf("inspecting container: %w", err)
}
containerInfo := container.Container{ContainerJSON: containerJSON}
if ignoreOneoff(containerInfo, config) {
return nil
}
ipNumbers := containerInfo.IPAddresses()
if len(ipNumbers) == 0 {
return nil
}
hostnames, err := hostname.Hostnames(containerInfo, config.HostnameLookup)
if err != nil {
return fmt.Errorf("getting hostnames: %w", err)
}
for _, hostname := range hostnames {
addAddress(entryGroup, hostname, ipNumbers)
}
if services := containerInfo.Services(); len(hostnames) > 0 {
addServices(entryGroup, hostnames[0], ipNumbers, services, containerInfo.Name())
}
return nil
}
func ignoreOneoff(containerInfo container.Container, config Config) bool {
if !config.IgnoreDockerComposeOneoff {
return false
}
oneoff, ok := containerInfo.Config.Labels["com.docker.compose.oneoff"]
if !ok {
return false
}
if oneoff != "True" {
return false
}
log.Logf(log.PriNotice, "Ignoring oneoff container: %s", containerInfo.ID)
return true
}
func handleExistingContainers(ctx context.Context, config Config, docker *client.Client, egs *entryGroups) {
containers, err := docker.ContainerList(ctx, typesContainer.ListOptions{})
if err != nil {
log.Logf(log.PriErr, "getting container list: %v", err)
}
for _, container := range containers {
err = handleContainer(ctx, docker, container.ID, egs, "start", config)
if err != nil {
log.Logf(log.PriErr, "handling container: %v", err)
continue
}
}
}
func listen(ctx context.Context, config Config, docker *client.Client, egs *entryGroups, started time.Time) {
filter := filters.NewArgs()
filter.Add("type", "container")
filter.Add("event", "die")
filter.Add("event", "kill")
filter.Add("event", "pause")
filter.Add("event", "start")
filter.Add("event", "unpause")
msgs, errs := docker.Events(ctx, events.ListOptions{
Filters: filter,
Since: strconv.FormatInt(started.Unix(), 10),
Until: "",
})
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGTERM)
for {
select {
case err := <-errs:
panic(fmt.Errorf("go error reading docker events: %w", err))
case msg := <-msgs:
err := handleContainer(ctx, docker, msg.ID, egs, msg.Status, config)
if err != nil {
log.Logf(log.PriErr, "handling container: %v", err)
}
case <-sig:
return
}
}
}