Skip to content
This repository was archived by the owner on Mar 22, 2022. It is now read-only.

Commit 0c59f0e

Browse files
gloursndeloof
authored andcommitted
Move Network functions to a dedicated file into internal directory
Signed-off-by: Guillaume Lours <[email protected]>
1 parent 88eb980 commit 0c59f0e

File tree

2 files changed

+232
-200
lines changed

2 files changed

+232
-200
lines changed

internal/network.go

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
package internal
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
compose "github.com/compose-spec/compose-go/types"
8+
"github.com/docker/docker/api/types"
9+
"github.com/docker/docker/api/types/container"
10+
"github.com/docker/docker/api/types/filters"
11+
"github.com/docker/docker/api/types/network"
12+
"github.com/docker/docker/client"
13+
"github.com/docker/docker/errdefs"
14+
"github.com/docker/go-connections/nat"
15+
)
16+
17+
func GetNetworksFromConfig(cli *client.Client, project string, config *compose.Config) (map[string]string, error) {
18+
networks := map[string]string{}
19+
for defaultNetworkName, networkConfig := range config.Networks {
20+
name, id, err := createNetwork(cli, project, defaultNetworkName, networkConfig)
21+
if err != nil {
22+
return nil, err
23+
}
24+
networks[name] = id
25+
}
26+
return networks, nil
27+
}
28+
29+
func createNetwork(cli *client.Client, project string, networkDefaultName string, netConfig compose.NetworkConfig) (string, string, error) {
30+
name := networkDefaultName
31+
if netConfig.Name != "" {
32+
name = netConfig.Name
33+
}
34+
createOptions := types.NetworkCreate{
35+
Driver: netConfig.Driver,
36+
Internal: netConfig.Internal,
37+
Attachable: netConfig.Attachable,
38+
Options: netConfig.DriverOpts,
39+
Labels: netConfig.Labels,
40+
}
41+
if createOptions.Driver == "" {
42+
createOptions.Driver = "bridge" //default driver
43+
}
44+
if createOptions.Labels == nil {
45+
createOptions.Labels = map[string]string{}
46+
}
47+
createOptions.Labels[LabelProject] = project
48+
createOptions.Labels[LabelNetwork] = name
49+
50+
if netConfig.External.External {
51+
_, err := cli.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
52+
fmt.Printf("Network %s declared as external. No new network will be created.\n", name)
53+
if errdefs.IsNotFound(err) {
54+
return "", "", fmt.Errorf("network %s declared as external, but could not be found. "+
55+
"Please create the network manually using `docker network create %s` and try again",
56+
name, name)
57+
}
58+
}
59+
60+
var networkID string
61+
resource, err := cli.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
62+
if err != nil {
63+
if errdefs.IsNotFound(err) {
64+
if netConfig.Ipam.Driver != "" || len(netConfig.Ipam.Config) > 0 {
65+
createOptions.IPAM = &network.IPAM{}
66+
67+
if netConfig.Ipam.Driver != "" {
68+
createOptions.IPAM.Driver = netConfig.Ipam.Driver
69+
}
70+
71+
for _, ipamConfig := range netConfig.Ipam.Config {
72+
config := network.IPAMConfig{
73+
Subnet: ipamConfig.Subnet,
74+
}
75+
createOptions.IPAM.Config = append(createOptions.IPAM.Config, config)
76+
}
77+
}
78+
var response types.NetworkCreateResponse
79+
if response, err = cli.NetworkCreate(context.Background(), name, createOptions); err != nil {
80+
return "", "", fmt.Errorf("failed to create network %s: %w", name, err)
81+
}
82+
networkID = response.ID
83+
} else {
84+
return "", "", err
85+
}
86+
} else {
87+
networkID = resource.ID
88+
}
89+
90+
return name, networkID, nil
91+
}
92+
93+
func RemoveNetworks(cli *client.Client, project string) error {
94+
networks, err := collectNetworks(cli, project)
95+
if err != nil {
96+
return err
97+
}
98+
for networkName, resource := range networks {
99+
err = destroyNetwork(cli, resource, networkName)
100+
if err != nil {
101+
return err
102+
}
103+
}
104+
return nil
105+
}
106+
107+
func destroyNetwork(cli *client.Client, networkResources []types.NetworkResource, networkName string) error {
108+
for _, networkResource := range networkResources {
109+
fmt.Printf("Deleting network %s ... ", networkName)
110+
err := cli.NetworkRemove(context.Background(), networkResource.ID)
111+
if err != nil {
112+
return err
113+
}
114+
fmt.Println(networkResource.Name)
115+
}
116+
return nil
117+
}
118+
119+
func collectNetworks(cli *client.Client, project string) (map[string][]types.NetworkResource, error) {
120+
networkList, err := cli.NetworkList(context.Background(), types.NetworkListOptions{
121+
Filters: filters.NewArgs(filters.Arg("label", LabelProject+"="+project)),
122+
})
123+
if err != nil {
124+
return nil, err
125+
}
126+
networks := map[string][]types.NetworkResource{}
127+
for _, r := range networkList {
128+
resource := r.Labels[LabelNetwork]
129+
l, ok := networks[resource]
130+
if !ok {
131+
l = []types.NetworkResource{r}
132+
} else {
133+
l = append(l, r)
134+
}
135+
networks[resource] = l
136+
137+
}
138+
return networks, nil
139+
}
140+
141+
func NetworkMode(serviceConfig compose.ServiceConfig, networks map[string]string) container.NetworkMode {
142+
mode := serviceConfig.NetworkMode
143+
if mode == "" {
144+
if len(networks) > 0 {
145+
for name := range getNetworksForService(serviceConfig) {
146+
if _, ok := networks[name]; ok {
147+
return container.NetworkMode(networks[name])
148+
}
149+
}
150+
}
151+
return "none"
152+
}
153+
return container.NetworkMode(mode)
154+
}
155+
156+
func getNetworksForService(config compose.ServiceConfig) map[string]*compose.ServiceNetworkConfig {
157+
if len(config.Networks) > 0 {
158+
return config.Networks
159+
}
160+
return map[string]*compose.ServiceNetworkConfig{"default": nil}
161+
}
162+
163+
164+
func BuildDefaultNetworkConfig(serviceConfig compose.ServiceConfig, networkMode container.NetworkMode) *network.NetworkingConfig {
165+
config := map[string]*network.EndpointSettings{}
166+
net := string(networkMode)
167+
config[net] = &network.EndpointSettings{
168+
Aliases: getAliases(serviceConfig.Name, serviceConfig.Networks[net]),
169+
}
170+
171+
return &network.NetworkingConfig{
172+
EndpointsConfig: config,
173+
}
174+
}
175+
176+
177+
func ConnectContainerToNetworks(context context.Context, cli *client.Client,
178+
serviceConfig compose.ServiceConfig, containerID string, networks map[string]string) error {
179+
for key, net := range serviceConfig.Networks {
180+
config := &network.EndpointSettings{
181+
Aliases: getAliases(serviceConfig.Name, net),
182+
}
183+
err := cli.NetworkConnect(context, networks[key], containerID, config)
184+
if err != nil {
185+
return err
186+
}
187+
}
188+
return nil
189+
}
190+
191+
func getAliases(serviceName string, c *compose.ServiceNetworkConfig) []string {
192+
aliases := []string{serviceName}
193+
if c != nil {
194+
aliases = append(aliases, c.Aliases...)
195+
}
196+
return aliases
197+
}
198+
199+
func BuildContainerPortBindingsOptions(serviceConfig compose.ServiceConfig) nat.PortMap {
200+
bindings := nat.PortMap{}
201+
for _, port := range serviceConfig.Ports {
202+
p := nat.Port(fmt.Sprintf("%d/%s", port.Target, port.Protocol))
203+
bind := []nat.PortBinding{}
204+
binding := nat.PortBinding{}
205+
if port.Published > 0 {
206+
binding.HostPort = fmt.Sprint(port.Published)
207+
}
208+
bind = append(bind, binding)
209+
bindings[p] = bind
210+
}
211+
return bindings
212+
}
213+
214+
func ExposedPorts(ports []compose.ServicePortConfig) nat.PortSet {
215+
natPorts := nat.PortSet{}
216+
for _, p := range ports {
217+
p := nat.Port(fmt.Sprintf("%d/%s", p.Target, p.Protocol))
218+
natPorts[p] = struct{}{}
219+
}
220+
return natPorts
221+
}

0 commit comments

Comments
 (0)