func (d *DockerProxy) RunByConfig(runConfig ContainerRunConfig) (string, error) { portBingds := map[string][]dockerclient.PortBinding{} exposedPorts := map[string]struct{}{} for _, port := range runConfig.PortBindings { pb := dockerclient.PortBinding{} pb.HostIp = "0.0.0.0" pb.HostPort = fmt.Sprintf("%d", port.GetHostPort()) key := fmt.Sprintf("%d/%s", port.ContainerPort, port.Protocal) portBingds[key] = []dockerclient.PortBinding{pb} exposedPorts[key] = struct{}{} } config := &dockerclient.ContainerConfig{} config.Image = runConfig.Image config.Env = runConfig.Envs config.Cmd = runConfig.Cmds config.Hostname = runConfig.Hostname config.ExposedPorts = exposedPorts hostConfig := &dockerclient.HostConfig{} hostConfig.PortBindings = portBingds hostConfig.Binds = runConfig.Bindings hostConfig.Dns = runConfig.DNS hostConfig.RestartPolicy = dockerclient.RestartPolicy{ Name: runConfig.RestartPolicy.Name, MaximumRetryCount: int64(runConfig.RestartPolicy.MaxTry), } config.HostConfig = *hostConfig cid, err := d.CreateContainer(config, runConfig.Name) if err != nil { return "", errors.New(fmt.Sprintf("Failed to create a container. name: %s, error: %s", runConfig.Name, err.Error())) } fmt.Printf("Container created. name:%s, id:%s\n", runConfig.Name, cid) if err := d.StartContainer(cid, hostConfig); err != nil { fmt.Printf("Failed to start container. name:%s, id:%s.\n", runConfig.Name, cid) return cid, err } fmt.Printf("Container start successfully. name:%s, id:%s.\n", runConfig.Name, cid) return cid, nil }
func (p HaproxyPlugin) GenerateProxyConfig() (*ProxyConfig, error) { logMessage(log.DebugLevel, "generating proxy config") containers, err := p.client.ListContainers(false, false, "") if err != nil { return nil, err } var hosts []*Host proxyUpstreams := map[string][]*Upstream{} hostChecks := map[string]string{} hostBalanceAlgorithms := map[string]string{} hostBackendOptions := map[string][]string{} hostSSLOnly := map[string]bool{} for _, cnt := range containers { cntId := cnt.Id[:12] // load interlock data cInfo, err := p.client.InspectContainer(cntId) if err != nil { return nil, err } env := cInfo.Config.Env interlockData := &InterlockData{} for _, e := range env { envParts := strings.Split(e, "=") if envParts[0] == "INTERLOCK_DATA" { b := bytes.NewBufferString(envParts[1]) if err := json.NewDecoder(b).Decode(&interlockData); err != nil { logMessage(log.WarnLevel, fmt.Sprintf("%s: unable to parse interlock data: %s", cntId, err)) } break } } hostname := cInfo.Config.Hostname domain := cInfo.Config.Domainname if interlockData.Hostname != "" { hostname = interlockData.Hostname } if interlockData.Domain != "" { domain = interlockData.Domain } if domain == "" { continue } if hostname != domain && hostname != "" { domain = fmt.Sprintf("%s.%s", hostname, domain) } if interlockData.Check != "" { if val, ok := hostChecks[domain]; ok { // check existing host check for different values if val != interlockData.Check { logMessage(log.WarnLevel, fmt.Sprintf("conflicting check specified for %s", domain)) } } else { hostChecks[domain] = interlockData.Check logMessage(log.DebugLevel, fmt.Sprintf("using custom check for %s: %s", domain, interlockData.Check)) } } checkInterval := 5000 if interlockData.CheckInterval != 0 { checkInterval = interlockData.CheckInterval logMessage(log.DebugLevel, fmt.Sprintf("using custom check interval for %s: %d", domain, checkInterval)) } hostBalanceAlgorithms[domain] = "roundrobin" if interlockData.BalanceAlgorithm != "" { hostBalanceAlgorithms[domain] = interlockData.BalanceAlgorithm } if len(interlockData.BackendOptions) > 0 { hostBackendOptions[domain] = interlockData.BackendOptions logMessage(log.DebugLevel, fmt.Sprintf("using backend options for %s: %s", domain, strings.Join(interlockData.BackendOptions, ","))) } hostSSLOnly[domain] = false if interlockData.SSLOnly { logMessage(log.DebugLevel, fmt.Sprintf("configuring ssl redirect for %s", domain)) hostSSLOnly[domain] = true } //host := cInfo.NetworkSettings.IpAddress ports := cInfo.NetworkSettings.Ports if len(ports) == 0 { logMessage(log.WarnLevel, fmt.Sprintf("%s: no ports exposed", cntId)) continue } var portDef dockerclient.PortBinding for _, v := range ports { if len(v) > 0 { portDef = dockerclient.PortBinding{ HostIp: v[0].HostIp, HostPort: v[0].HostPort, } break } } if p.pluginConfig.ProxyBackendOverrideAddress != "" { portDef.HostIp = p.pluginConfig.ProxyBackendOverrideAddress } addr := fmt.Sprintf("%s:%s", portDef.HostIp, portDef.HostPort) if interlockData.Port != 0 { interlockPort := fmt.Sprintf("%d", interlockData.Port) for k, v := range ports { parts := strings.Split(k, "/") if parts[0] == interlockPort { port := v[0] logMessage(log.DebugLevel, fmt.Sprintf("%s: found specified port %s exposed as %s", domain, interlockPort, port.HostPort)) addr = fmt.Sprintf("%s:%s", portDef.HostIp, port.HostPort) break } } } container_name := cInfo.Name[1:] up := &Upstream{ Addr: addr, Container: container_name, CheckInterval: checkInterval, } logMessage(log.InfoLevel, fmt.Sprintf("%s: upstream=%s container=%s", domain, addr, container_name)) for _, alias := range interlockData.AliasDomains { logMessage(log.DebugLevel, fmt.Sprintf("adding alias %s for %s", alias, cntId)) proxyUpstreams[alias] = append(proxyUpstreams[alias], up) } proxyUpstreams[domain] = append(proxyUpstreams[domain], up) } for k, v := range proxyUpstreams { name := strings.Replace(k, ".", "_", -1) host := &Host{ Name: name, Domain: k, Upstreams: v, Check: hostChecks[k], BalanceAlgorithm: hostBalanceAlgorithms[k], BackendOptions: hostBackendOptions[k], SSLOnly: hostSSLOnly[k], } logMessage(log.DebugLevel, fmt.Sprintf("adding host name=%s domain=%s", host.Name, host.Domain)) hosts = append(hosts, host) } // generate config cfg := &ProxyConfig{ Hosts: hosts, PluginConfig: p.pluginConfig, } return cfg, nil }
func (p NginxPlugin) generateNginxConfig() (*NginxConfig, error) { containers, err := p.client.ListContainers(false, false, "") if err != nil { return nil, err } var hosts []*Host upstreamServers := map[string][]string{} serverNames := map[string][]string{} //hostBalanceAlgorithms := map[string]string{} hostSSL := map[string]bool{} hostSSLCert := map[string]string{} hostSSLCertKey := map[string]string{} hostSSLOnly := map[string]bool{} hostWebsocketEndpoints := map[string][]string{} for _, c := range containers { cntId := c.Id[:12] // load interlock data cInfo, err := p.client.InspectContainer(cntId) if err != nil { return nil, err } env := cInfo.Config.Env interlockData := &InterlockData{} for _, e := range env { envParts := strings.Split(e, "=") if envParts[0] == "INTERLOCK_DATA" { b := bytes.NewBufferString(envParts[1]) if err := json.NewDecoder(b).Decode(&interlockData); err != nil { logMessage(log.WarnLevel, fmt.Sprintf("%s: unable to parse interlock data: %s", cntId, err)) } break } } hostname := cInfo.Config.Hostname domain := cInfo.Config.Domainname if interlockData.Hostname != "" { hostname = interlockData.Hostname } if interlockData.Domain != "" { domain = interlockData.Domain } if domain == "" { continue } if hostname != domain && hostname != "" { domain = fmt.Sprintf("%s.%s", hostname, domain) } // check if the first server name is there; if not, add // this happens if there are multiple backend containers if _, ok := serverNames[domain]; !ok { serverNames[domain] = []string{domain} } hostSSL[domain] = interlockData.SSL hostSSLOnly[domain] = false if interlockData.SSLOnly { logMessage(log.DebugLevel, fmt.Sprintf("configuring ssl redirect for %s", domain)) hostSSLOnly[domain] = true } // set cert paths baseCertPath := p.pluginConfig.SSLCertDir if interlockData.SSLCert != "" { certPath := filepath.Join(baseCertPath, interlockData.SSLCert) logMessage(log.InfoLevel, fmt.Sprintf("ssl cert for %s: %s", domain, certPath)) hostSSLCert[domain] = certPath } if interlockData.SSLCertKey != "" { keyPath := filepath.Join(baseCertPath, interlockData.SSLCertKey) logMessage(log.InfoLevel, fmt.Sprintf("ssl key for %s: %s", domain, keyPath)) hostSSLCertKey[domain] = keyPath } ports := cInfo.NetworkSettings.Ports if len(ports) == 0 { logMessage(log.WarnLevel, fmt.Sprintf("%s: no ports exposed", cntId)) continue } var portDef dockerclient.PortBinding for _, v := range ports { if len(v) > 0 { portDef = dockerclient.PortBinding{ HostIp: v[0].HostIp, HostPort: v[0].HostPort, } break } } if p.pluginConfig.ProxyBackendOverrideAddress != "" { portDef.HostIp = p.pluginConfig.ProxyBackendOverrideAddress } addr := fmt.Sprintf("%s:%s", portDef.HostIp, portDef.HostPort) if interlockData.Port != 0 { interlockPort := fmt.Sprintf("%d", interlockData.Port) for k, v := range ports { parts := strings.Split(k, "/") if parts[0] == interlockPort { port := v[0] logMessage(log.DebugLevel, fmt.Sprintf("%s: found specified port %s exposed as %s", domain, interlockPort, port.HostPort)) addr = fmt.Sprintf("%s:%s", portDef.HostIp, port.HostPort) break } } } // websocket endpoints for _, ws := range interlockData.WebsocketEndpoints { hostWebsocketEndpoints[domain] = append(hostWebsocketEndpoints[domain], ws) } logMessage(log.InfoLevel, fmt.Sprintf("%s: upstream=%s", domain, addr)) for _, alias := range interlockData.AliasDomains { logMessage(log.DebugLevel, fmt.Sprintf("adding alias %s for %s", alias, cntId)) serverNames[domain] = append(serverNames[domain], alias) } upstreamServers[domain] = append(upstreamServers[domain], addr) } for k, v := range upstreamServers { h := &Host{ ServerNames: serverNames[k], // TODO: make configurable for TCP via InterlockData Port: p.pluginConfig.Port, SSLPort: p.pluginConfig.SSLPort, SSL: hostSSL[k], SSLCert: hostSSLCert[k], SSLCertKey: hostSSLCertKey[k], SSLOnly: hostSSLOnly[k], WebsocketEndpoints: hostWebsocketEndpoints[k], } servers := []*Server{} for _, s := range v { srv := &Server{ Addr: s, } servers = append(servers, srv) } up := &Upstream{ Name: k, Servers: servers, } h.Upstream = up hosts = append(hosts, h) } return &NginxConfig{ *p.pluginConfig, hosts, }, nil }
func (p *NginxLoadBalancer) GenerateProxyConfig() (*Config, error) { containers, err := p.client.ListContainers(false, false, "") if err != nil { return nil, err } var hosts []*Host upstreamServers := map[string][]string{} serverNames := map[string][]string{} //hostBalanceAlgorithms := map[string]string{} hostSSL := map[string]bool{} hostSSLCert := map[string]string{} hostSSLCertKey := map[string]string{} hostSSLOnly := map[string]bool{} hostSSLBackend := map[string]bool{} hostWebsocketEndpoints := map[string][]string{} for _, c := range containers { cntId := c.Id[:12] // load interlock data cInfo, err := p.client.InspectContainer(cntId) if err != nil { return nil, err } hostname := cInfo.Config.Hostname domain := cInfo.Config.Domainname if v, ok := cInfo.Config.Labels[ext.InterlockHostnameLabel]; ok { hostname = v } if v, ok := cInfo.Config.Labels[ext.InterlockDomainLabel]; ok { domain = v } if domain == "" { continue } if hostname != domain && hostname != "" { domain = fmt.Sprintf("%s.%s", hostname, domain) } // check if the first server name is there; if not, add // this happens if there are multiple backend containers if _, ok := serverNames[domain]; !ok { serverNames[domain] = []string{domain} } if _, ok := cInfo.Config.Labels[ext.InterlockSSLLabel]; ok { hostSSL[domain] = true } hostSSLOnly[domain] = false if _, ok := cInfo.Config.Labels[ext.InterlockSSLOnlyLabel]; ok { log().Infof("configuring ssl redirect for %s", domain) hostSSLOnly[domain] = true } // check ssl backend hostSSLBackend[domain] = false if _, ok := cInfo.Config.Labels[ext.InterlockSSLBackendLabel]; ok { log().Debugf("configuring ssl backend for %s", domain) hostSSLBackend[domain] = true } // set cert paths baseCertPath := p.cfg.SSLCertPath if v, ok := cInfo.Config.Labels[ext.InterlockSSLCertLabel]; ok { certPath := filepath.Join(baseCertPath, v) log().Infof("ssl cert for %s: %s", domain, certPath) hostSSLCert[domain] = certPath } if v, ok := cInfo.Config.Labels[ext.InterlockSSLCertKeyLabel]; ok { keyPath := filepath.Join(baseCertPath, v) log().Infof("ssl key for %s: %s", domain, keyPath) hostSSLCertKey[domain] = keyPath } ports := cInfo.NetworkSettings.Ports if len(ports) == 0 { log().Warnf("%s: no ports exposed", cntId) continue } var portDef dockerclient.PortBinding for _, v := range ports { if len(v) > 0 { portDef = dockerclient.PortBinding{ HostIp: v[0].HostIp, HostPort: v[0].HostPort, } break } } if p.cfg.BackendOverrideAddress != "" { portDef.HostIp = p.cfg.BackendOverrideAddress } addr := fmt.Sprintf("%s:%s", portDef.HostIp, portDef.HostPort) if v, ok := cInfo.Config.Labels[ext.InterlockPortLabel]; ok { interlockPort := v for k, x := range ports { parts := strings.Split(k, "/") if parts[0] == interlockPort { port := x[0] log().Debugf("%s: found specified port %s exposed as %s", domain, interlockPort, port.HostPort) addr = fmt.Sprintf("%s:%s", portDef.HostIp, port.HostPort) break } } } // "parse" multiple labels for websocket endpoints websocketEndpoints := []string{} for l, v := range cInfo.Config.Labels { // this is for labels like interlock.websocket_endpoint.1=foo if strings.Index(l, ext.InterlockWebsocketEndpointLabel) > -1 { websocketEndpoints = append(websocketEndpoints, v) } } log().Debugf("websocket endpoints: %v", websocketEndpoints) // websocket endpoints for _, ws := range websocketEndpoints { hostWebsocketEndpoints[domain] = append(hostWebsocketEndpoints[domain], ws) } // "parse" multiple labels for alias domains aliasDomains := []string{} for l, v := range cInfo.Config.Labels { // this is for labels like interlock.alias_domain.1=foo.local if strings.Index(l, ext.InterlockAliasDomainLabel) > -1 { aliasDomains = append(aliasDomains, v) } } log().Debugf("alias domains: %v", aliasDomains) for _, alias := range aliasDomains { log().Debugf("adding alias %s for %s", alias, cntId) serverNames[domain] = append(serverNames[domain], alias) } log().Infof("%s: upstream=%s", domain, addr) upstreamServers[domain] = append(upstreamServers[domain], addr) } for k, v := range upstreamServers { h := &Host{ ServerNames: serverNames[k], Port: p.cfg.Port, SSLPort: p.cfg.SSLPort, SSL: hostSSL[k], SSLCert: hostSSLCert[k], SSLCertKey: hostSSLCertKey[k], SSLOnly: hostSSLOnly[k], SSLBackend: hostSSLBackend[k], WebsocketEndpoints: hostWebsocketEndpoints[k], } servers := []*Server{} for _, s := range v { srv := &Server{ Addr: s, } servers = append(servers, srv) } up := &Upstream{ Name: k, Servers: servers, } h.Upstream = up hosts = append(hosts, h) } return &Config{ Hosts: hosts, Config: p.cfg, }, nil }
func (p *HAProxyLoadBalancer) GenerateProxyConfig() (*Config, error) { log().Debug("generating proxy config") containers, err := p.client.ListContainers(false, false, "") if err != nil { return nil, err } var hosts []*Host proxyUpstreams := map[string][]*Upstream{} hostChecks := map[string]string{} hostBalanceAlgorithms := map[string]string{} hostBackendOptions := map[string][]string{} hostSSLOnly := map[string]bool{} hostSSLBackend := map[string]bool{} hostSSLBackendTLSVerify := map[string]string{} // TODO: instead of setting defaults here use // SetDefaultConfig in the utils package for _, cnt := range containers { cntId := cnt.Id[:12] // load interlock data cInfo, err := p.client.InspectContainer(cntId) if err != nil { return nil, err } hostname := cInfo.Config.Hostname domain := cInfo.Config.Domainname if v, ok := cInfo.Config.Labels[ext.InterlockHostnameLabel]; ok { hostname = v } if v, ok := cInfo.Config.Labels[ext.InterlockDomainLabel]; ok { domain = v } if domain == "" { continue } if hostname != domain && hostname != "" { domain = fmt.Sprintf("%s.%s", hostname, domain) } if v, ok := cInfo.Config.Labels[ext.InterlockHealthCheckLabel]; ok { if val, ok := hostChecks[domain]; ok { // check existing host check for different values if val != v { log().Warnf("conflicting check specified for %s", domain) } } else { hostChecks[domain] = v log().Debugf("using custom check for %s: %s", domain, v) } } checkInterval := 5000 if v, ok := cInfo.Config.Labels[ext.InterlockHealthCheckIntervalLabel]; ok && v != "" { i, err := strconv.Atoi(v) if err != nil { return nil, err } if i != 0 { checkInterval = i log().Debugf("using custom check interval for %s: %d", domain, checkInterval) } } hostBalanceAlgorithms[domain] = "roundrobin" if v, ok := cInfo.Config.Labels[ext.InterlockBalanceAlgorithmLabel]; ok && v != "" { hostBalanceAlgorithms[domain] = v } backendOptions := []string{} for l, v := range cInfo.Config.Labels { // this is for labels like interlock.backend_option.1=foo if strings.Index(l, ext.InterlockBackendOptionLabel) > -1 { backendOptions = append(backendOptions, v) } } if len(backendOptions) > 0 { hostBackendOptions[domain] = backendOptions log().Debugf("using backend options for %s: %s", domain, strings.Join(backendOptions, ",")) } hostSSLOnly[domain] = false if _, ok := cInfo.Config.Labels[ext.InterlockSSLOnlyLabel]; ok { log().Debugf("configuring ssl redirect for %s", domain) hostSSLOnly[domain] = true } // ssl backend hostSSLBackend[domain] = false if _, ok := cInfo.Config.Labels[ext.InterlockSSLBackendLabel]; ok { hostSSLBackend[domain] = true sslBackendTLSVerify := "none" if v, ok := cInfo.Config.Labels[ext.InterlockSSLBackendTLSVerifyLabel]; ok { sslBackendTLSVerify = v } hostSSLBackendTLSVerify[domain] = sslBackendTLSVerify log().Debugf("configuring ssl backend for %s verify=%s", domain, sslBackendTLSVerify) } //host := cInfo.NetworkSettings.IpAddress ports := cInfo.NetworkSettings.Ports if len(ports) == 0 { log().Warnf("%s: no ports exposed", cntId) continue } var portDef dockerclient.PortBinding for _, v := range ports { if len(v) > 0 { portDef = dockerclient.PortBinding{ HostIp: v[0].HostIp, HostPort: v[0].HostPort, } break } } if p.cfg.BackendOverrideAddress != "" { portDef.HostIp = p.cfg.BackendOverrideAddress } addr := fmt.Sprintf("%s:%s", portDef.HostIp, portDef.HostPort) if v, ok := cInfo.Config.Labels[ext.InterlockPortLabel]; ok { for k, x := range ports { parts := strings.Split(k, "/") if parts[0] == v { port := x[0] log().Debugf("%s: found specified port %s exposed as %s", domain, v, port.HostPort) addr = fmt.Sprintf("%s:%s", portDef.HostIp, port.HostPort) break } } } container_name := cInfo.Name[1:] up := &Upstream{ Addr: addr, Container: container_name, CheckInterval: checkInterval, } log().Infof("%s: upstream=%s container=%s", domain, addr, container_name) // "parse" multiple labels for alias domains aliasDomains := []string{} for l, v := range cInfo.Config.Labels { // this is for labels like interlock.alias_domain.1=foo.local if strings.Index(l, ext.InterlockAliasDomainLabel) > -1 { aliasDomains = append(aliasDomains, v) } } log().Debugf("alias domains: %v", aliasDomains) for _, alias := range aliasDomains { log().Debugf("adding alias %s for %s", alias, cntId) proxyUpstreams[alias] = append(proxyUpstreams[alias], up) } proxyUpstreams[domain] = append(proxyUpstreams[domain], up) } for k, v := range proxyUpstreams { name := strings.Replace(k, ".", "_", -1) host := &Host{ Name: name, Domain: k, Upstreams: v, Check: hostChecks[k], BalanceAlgorithm: hostBalanceAlgorithms[k], BackendOptions: hostBackendOptions[k], SSLOnly: hostSSLOnly[k], SSLBackend: hostSSLBackend[k], SSLBackendTLSVerify: hostSSLBackendTLSVerify[k], } log().Debugf("adding host name=%s domain=%s", host.Name, host.Domain) hosts = append(hosts, host) } // generate config cfg := &Config{ Hosts: hosts, Config: p.cfg, } return cfg, nil }