-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnetwork.go
113 lines (100 loc) · 3.65 KB
/
network.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
package dev
import (
"github.com/docker/docker/api/types"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/wish/dev/compose"
"github.com/wish/dev/config"
"github.com/wish/dev/docker"
)
// Network is an external docker network that dev manages.
type Network struct {
Name string
Config *types.NetworkCreate
}
// NewNetwork is the Network constructor.
func NewNetwork(name string, config *types.NetworkCreate) *Network {
return &Network{
Name: name,
Config: config,
}
}
// create any external network configured in the dev tool if it does not exist
// already. It returns the network id used to indentify the network by docker.
func (n *Network) create() string {
networkID, err := docker.NetworkIDFromName(n.Name)
if err != nil {
err = errors.Wrapf(err, "Error checking if network %s exists", n.Name)
log.Fatal(err)
}
if networkID == "" {
networkID, err = docker.NetworkCreate(n.Name, n.Config)
if err != nil {
log.Fatal(err)
}
log.Infof("Created %s network %s", n.Name, networkID)
} else {
log.Debugf("Network %s already exists with id %s", n.Name, networkID)
}
return networkID
}
// createNetworkServiceMap creates a mapping from the networks configured by dev
// to a list of the services that use them in the projects docker-compose files.
func (n *Network) createNetworkServiceMap(devConfig *config.Dev, project *config.Project,
networkIDMap map[string]string) map[string][]string {
serviceNetworkMap := make(map[string][]string, len(networkIDMap))
for _, composeFilename := range project.DockerComposeFilenames {
composeConfig, err := compose.Parse(devConfig.GetFs(), project.Directory, composeFilename)
if err != nil {
log.Fatal("Failed to parse docker-compose appConfig file: ", err)
}
for _, service := range composeConfig.Services {
for name := range service.Networks {
if _, ok := networkIDMap[name]; ok {
serviceNetworkMap[name] = append(serviceNetworkMap[name], service.Name)
}
}
}
}
return serviceNetworkMap
}
// verifyContainerConfig performs container operations necessary to get the
// containers into the state specified in the dev appConfig files.
//
// Networks do not persist reboots. Container configured with an old network id
// that no longer exists will not be able to start (docker-compose up will fail
// when it attempts to start the container). These containers must be removed
// before we attempt to start the container.
func (n *Network) verifyContainerConfig(appConfig *config.Dev, project *config.Project, networkID string) {
networkIDMap := map[string]string{
n.Name: networkID,
}
networkServiceMap := n.createNetworkServiceMap(appConfig, project, networkIDMap)
for networkName, services := range networkServiceMap {
networkID := networkIDMap[networkName]
err := docker.RemoveContainerIfRequired(networkName, networkID, services)
if err != nil {
log.Fatal(err)
}
}
}
// PreRun implements the Dependency interface. It will destroy any containers
// that are attached to a no longer existing network of the same name such that
// the containers can be created with the correct network.
func (n *Network) PreRun(command string, appConfig *config.Dev, project *Project) {
if !SliceContainsString([]string{UP, SH}, command) {
return
}
networkID := n.create()
n.verifyContainerConfig(appConfig, project.Config, networkID)
}
// Dependencies implements the Dependency interface. At this time a Network
// cannot have dependencies so it returns an empty slice.
func (n *Network) Dependencies() []string {
return []string{}
}
// GetName returns the name of the network as named by the user in the
// configuration file.
func (n *Network) GetName() string {
return n.Name
}