Files
dokku/plugins/network/network.go

202 lines
5.1 KiB
Go
Raw Permalink Normal View History

package network
import (
"fmt"
"net"
"os"
2017-10-04 00:48:02 -04:00
"path/filepath"
"strconv"
"strings"
2017-10-02 16:50:05 -07:00
"github.com/dokku/dokku/plugins/common"
)
2017-10-02 16:50:05 -07:00
var (
// DefaultProperties is a map of all valid network properties with corresponding default property values
DefaultProperties = map[string]string{
"attach-post-create": "",
"attach-post-deploy": "",
"bind-all-interfaces": "",
"initial-network": "",
"static-web-listener": "",
"tld": "",
2017-10-02 16:50:05 -07:00
}
// GlobalProperties is a map of all valid global network properties
GlobalProperties = map[string]bool{
"attach-post-create": true,
"attach-post-deploy": true,
"bind-all-interfaces": true,
"initial-network": true,
"tld": true,
}
2017-10-02 16:50:05 -07:00
)
2017-09-03 17:31:14 -04:00
// BuildConfig builds network config files
func BuildConfig(appName string) error {
2017-09-03 17:31:14 -04:00
if !common.IsDeployed(appName) {
return nil
2017-09-03 17:31:14 -04:00
}
if staticWebListener := reportStaticWebListener(appName); staticWebListener != "" {
return nil
}
appRoot := common.AppRoot(appName)
results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
Trigger: "ps-current-scale",
Args: []string{appName},
})
if err != nil {
return err
2017-09-03 17:31:14 -04:00
}
scale, err := common.ParseScaleOutput(results.StdoutBytes())
2017-09-03 17:31:14 -04:00
if err != nil {
return err
2017-09-03 17:31:14 -04:00
}
if len(scale) == 0 {
return nil
}
2017-09-03 17:31:14 -04:00
if common.GetAppScheduler(appName) != "docker-local" {
return nil
}
common.LogInfo1(fmt.Sprintf("Ensuring network configuration is in sync for %s", appName))
2017-09-03 17:31:14 -04:00
for processType, procCount := range scale {
containerIndex := int32(0)
2017-09-03 17:31:14 -04:00
for containerIndex < procCount {
containerIndex++
containerIndexString := strconv.FormatInt(int64(containerIndex), 10)
2019-04-08 16:36:30 -04:00
containerIDFile := fmt.Sprintf("%v/CONTAINER.%v.%v", appRoot, processType, containerIndex)
2017-09-03 17:31:14 -04:00
containerID := common.ReadFirstLine(containerIDFile)
if containerID == "" || !common.ContainerIsRunning(containerID) {
continue
}
2019-04-08 16:36:30 -04:00
ipAddress := GetContainerIpaddress(appName, processType, containerID)
2017-09-03 17:31:14 -04:00
if ipAddress != "" {
args := []string{appName, processType, containerIndexString, ipAddress}
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
Trigger: "network-write-ipaddr",
Args: args,
})
2017-09-03 17:31:14 -04:00
if err != nil {
common.LogWarn(err.Error())
}
}
}
}
return nil
2017-09-03 17:31:14 -04:00
}
2017-07-22 15:26:23 -06:00
// GetContainerIpaddress returns the ipaddr for a given app container
2019-04-08 16:36:30 -04:00
func GetContainerIpaddress(appName, processType, containerID string) (ipAddr string) {
if processType == "web" {
if staticWebListener := reportStaticWebListener(appName); staticWebListener != "" {
ip, _, err := net.SplitHostPort(staticWebListener)
if err == nil {
return ip
}
ip2 := net.ParseIP(staticWebListener)
if ip2 != nil {
return ip2.String()
}
return "127.0.0.1"
}
}
if b, err := common.DockerInspect(containerID, "{{ .HostConfig.NetworkMode }}"); err == nil {
if string(b[:]) == "host" {
return "127.0.0.1"
}
}
initialNetwork := reportComputedInitialNetwork(appName)
if initialNetwork == "" {
initialNetwork = "bridge"
}
b, err := common.DockerInspect(containerID, fmt.Sprintf("{{ $network := index .NetworkSettings.Networks \"%s\" }}{{ $network.IPAddress}}", initialNetwork))
if err != nil || len(b) == 0 {
2021-07-09 21:14:06 -04:00
// Deprecated: docker < 1.9 compatibility
b, err = common.DockerInspect(containerID, "{{ .NetworkSettings.IPAddress }}")
}
if err == nil {
return string(b[:])
}
2017-10-02 16:50:05 -07:00
return
}
2017-10-04 00:48:02 -04:00
// GetListeners returns a string array of app listeners
func GetListeners(appName string, processType string) []string {
if processType == "web" {
if staticWebListener := reportStaticWebListener(appName); staticWebListener != "" {
return []string{staticWebListener}
}
}
appRoot := common.AppRoot(appName)
2017-10-04 00:48:02 -04:00
ipPrefix := fmt.Sprintf("/IP.%s.", processType)
portPrefix := fmt.Sprintf("/PORT.%s.", processType)
files, _ := filepath.Glob(appRoot + ipPrefix + "*")
2017-10-04 00:48:02 -04:00
var listeners []string
for _, ipfile := range files {
portfile := strings.Replace(ipfile, ipPrefix, portPrefix, 1)
2017-10-04 00:48:02 -04:00
ipAddress := common.ReadFirstLine(ipfile)
port := common.ReadFirstLine(portfile)
if port == "" {
port = "5000"
}
2017-10-04 00:48:02 -04:00
listeners = append(listeners, fmt.Sprintf("%s:%s", ipAddress, port))
}
return listeners
}
// HasNetworkConfig returns whether the network configuration for a given app exists
func HasNetworkConfig(appName string) bool {
appRoot := common.AppRoot(appName)
ipfile := fmt.Sprintf("%v/IP.web.1", appRoot)
portfile := fmt.Sprintf("%v/PORT.web.1", appRoot)
if common.FileExists(ipfile) && common.FileExists(portfile) {
return true
}
return reportStaticWebListener(appName) != ""
}
// ClearNetworkConfig removes old IP and PORT files for a newly cloned app
func ClearNetworkConfig(appName string) bool {
appRoot := common.AppRoot(appName)
success := true
ipFiles, _ := filepath.Glob(appRoot + "/IP.*")
for _, file := range ipFiles {
if err := os.Remove(file); err != nil {
common.LogWarn(fmt.Sprintf("Unable to remove file %s", file))
success = false
}
}
portFiles, _ := filepath.Glob(appRoot + "/PORT.*")
for _, file := range portFiles {
if err := os.Remove(file); err != nil {
common.LogWarn(fmt.Sprintf("Unable to remove file %s", file))
success = false
}
}
return success
}