-
Notifications
You must be signed in to change notification settings - Fork 49
/
plugin.go
134 lines (104 loc) · 3.33 KB
/
plugin.go
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
package plugin
import (
"fmt"
"net"
"net/http"
"regexp"
"time"
docker "github.com/docker/docker/client"
"github.com/gorilla/handlers"
"github.com/mitchellh/mapstructure"
"github.com/vishvananda/netlink"
"github.com/devplayer0/docker-net-dhcp/pkg/util"
)
// DriverName is the name of the Docker Network Driver
const DriverName string = "net-dhcp"
const defaultLeaseTimeout = 10 * time.Second
var driverRegexp = regexp.MustCompile(`^ghcr\.io/devplayer0/docker-net-dhcp:.+$`)
// IsDHCPPlugin checks if a Docker network driver is an instance of this plugin
func IsDHCPPlugin(driver string) bool {
return driverRegexp.MatchString(driver)
}
// DHCPNetworkOptions contains options for the DHCP network driver
type DHCPNetworkOptions struct {
Bridge string
IPv6 bool
LeaseTimeout time.Duration `mapstructure:"lease_timeout"`
IgnoreConflicts bool `mapstructure:"ignore_conflicts"`
SkipRoutes bool `mapstructure:"skip_routes"`
}
func decodeOpts(input interface{}) (DHCPNetworkOptions, error) {
var opts DHCPNetworkOptions
optsDecoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &opts,
ErrorUnused: true,
WeaklyTypedInput: true,
DecodeHook: mapstructure.ComposeDecodeHookFunc(
mapstructure.StringToTimeDurationHookFunc(),
),
})
if err != nil {
return opts, fmt.Errorf("failed to create options decoder: %w", err)
}
if err := optsDecoder.Decode(input); err != nil {
return opts, err
}
return opts, nil
}
type joinHint struct {
IPv4 *netlink.Addr
IPv6 *netlink.Addr
Gateway string
}
// Plugin is the DHCP network plugin
type Plugin struct {
awaitTimeout time.Duration
docker *docker.Client
server http.Server
joinHints map[string]joinHint
persistentDHCP map[string]*dhcpManager
}
// NewPlugin creates a new Plugin
func NewPlugin(awaitTimeout time.Duration) (*Plugin, error) {
client, err := docker.NewClient("unix:///run/docker.sock", "v1.13.1", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to create docker client: %w", err)
}
p := Plugin{
awaitTimeout: awaitTimeout,
docker: client,
joinHints: make(map[string]joinHint),
persistentDHCP: make(map[string]*dhcpManager),
}
mux := http.NewServeMux()
mux.HandleFunc("/NetworkDriver.GetCapabilities", p.apiGetCapabilities)
mux.HandleFunc("/NetworkDriver.CreateNetwork", p.apiCreateNetwork)
mux.HandleFunc("/NetworkDriver.DeleteNetwork", p.apiDeleteNetwork)
mux.HandleFunc("/NetworkDriver.CreateEndpoint", p.apiCreateEndpoint)
mux.HandleFunc("/NetworkDriver.EndpointOperInfo", p.apiEndpointOperInfo)
mux.HandleFunc("/NetworkDriver.DeleteEndpoint", p.apiDeleteEndpoint)
mux.HandleFunc("/NetworkDriver.Join", p.apiJoin)
mux.HandleFunc("/NetworkDriver.Leave", p.apiLeave)
p.server = http.Server{
Handler: handlers.CustomLoggingHandler(nil, mux, util.WriteAccessLog),
}
return &p, nil
}
// Listen starts the plugin server
func (p *Plugin) Listen(bindSock string) error {
l, err := net.Listen("unix", bindSock)
if err != nil {
return err
}
return p.server.Serve(l)
}
// Close stops the plugin server
func (p *Plugin) Close() error {
if err := p.docker.Close(); err != nil {
return fmt.Errorf("failed to close docker client: %w", err)
}
if err := p.server.Close(); err != nil {
return fmt.Errorf("failed to close http server: %w", err)
}
return nil
}