Skip to content

Commit

Permalink
Adding full sync with external LB provider, changed LB model and added
Browse files Browse the repository at this point in the history
provider healthcheck
  • Loading branch information
Prachi Damle authored and Prachi Damle committed Apr 15, 2016
1 parent 55603bf commit 4d1a065
Show file tree
Hide file tree
Showing 10 changed files with 451 additions and 127 deletions.
Binary file removed bin/external-lb
Binary file not shown.
144 changes: 144 additions & 0 deletions external-lb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package main

import (
"fmt"
"github.com/Sirupsen/logrus"
"github.com/rancher/external-lb/model"
"strings"
)

func UpdateProviderLBConfigs(metadataConfigs map[string]model.LBConfig) error {
providerConfigs, err := getProviderLBConfigs()
if err != nil {
return fmt.Errorf("Provider error reading lb configs: %v", err)
}
logrus.Debugf("Rancher LB configs from provider: %v", providerConfigs)

removeExtraConfigs(metadataConfigs, providerConfigs)

addMissingConfigs(metadataConfigs, providerConfigs)

updateExistingConfigs(metadataConfigs, providerConfigs)

return nil
}

func getProviderLBConfigs() (map[string]model.LBConfig, error) {
logrus.Debugf("Getting Rancher LB configs from provider: %v", provider.GetName())
allConfigs, err := provider.GetLBConfigs()
if err != nil {
logrus.Debugf("Error Getting Rancher LB configs from provider: %v", err)
return nil, err
}
rancherConfigs := make(map[string]model.LBConfig, len(allConfigs))
suffix := "_rancher.internal"
for _, value := range allConfigs {
if strings.HasSuffix(value.LBTargetName, suffix) {
rancherConfigs[value.LBEndpoint] = value
}
}
return rancherConfigs, nil
}

func removeExtraConfigs(metadataConfigs map[string]model.LBConfig, providerConfigs map[string]model.LBConfig) []model.LBConfig {
var toRemove []model.LBConfig
for key := range providerConfigs {
if _, ok := metadataConfigs[key]; !ok {
toRemove = append(toRemove, providerConfigs[key])
}
}

if len(toRemove) == 0 {
logrus.Debug("No LB configs to remove")
} else {
logrus.Infof("LB configs to remove: %v", toRemove)
}
return updateProvider(toRemove, &Remove)
}

func addMissingConfigs(metadataConfigs map[string]model.LBConfig, providerConfigs map[string]model.LBConfig) []model.LBConfig {
var toAdd []model.LBConfig
for key := range metadataConfigs {
if _, ok := providerConfigs[key]; !ok {
toAdd = append(toAdd, metadataConfigs[key])
}
}
if len(toAdd) == 0 {
logrus.Debug("No LB configs to add")
} else {
logrus.Infof("LB configs to add: %v", toAdd)
}
return updateProvider(toAdd, &Add)
}

func updateExistingConfigs(metadataConfigs map[string]model.LBConfig, providerConfigs map[string]model.LBConfig) []model.LBConfig {
var toUpdate []model.LBConfig
for key := range metadataConfigs {
if _, ok := providerConfigs[key]; ok {
mLBConfig := metadataConfigs[key]
pLBConfig := providerConfigs[key]
var update bool
//check that the targetName and targets match
if mLBConfig.LBTargetName == pLBConfig.LBTargetName {
if len(mLBConfig.LBTargets) != len(pLBConfig.LBTargets) {
update = true
}
//check if any target have changed
for _, mTarget := range mLBConfig.LBTargets {
targetExists := false
for _, pTarget := range pLBConfig.LBTargets {
if pTarget.HostIP == mTarget.HostIP && pTarget.Port == mTarget.Port {
targetExists = true
break
}
}
if !targetExists {
//lb target changed, update the config on provider
update = true
break
}
}
}

if update {
toUpdate = append(toUpdate, metadataConfigs[key])
}
}
}

if len(toUpdate) == 0 {
logrus.Debug("No LB configs to update")
} else {
logrus.Infof("LB configs to update: %v", toUpdate)
}

return updateProvider(toUpdate, &Update)
}

func updateProvider(toChange []model.LBConfig, op *Op) []model.LBConfig {
var changed []model.LBConfig
for _, value := range toChange {
switch *op {
case Add:
logrus.Infof("Adding LB config: %v", value)
if err := provider.AddLBConfig(value); err != nil {
logrus.Errorf("Failed to add LB config to provider %v: %v", value, err)
} else {
changed = append(changed, value)
}
case Remove:
logrus.Infof("Removing LB config: %v", value)
if err := provider.RemoveLBConfig(value); err != nil {
logrus.Errorf("Failed to remove LB config from provider %v: %v", value, err)
}
case Update:
logrus.Infof("Updating LB config: %v", value)
if err := provider.UpdateLBConfig(value); err != nil {
logrus.Errorf("Failed to update LB config to provider %v: %v", value, err)
} else {
changed = append(changed, value)
}
}
}
return changed
}
1 change: 0 additions & 1 deletion gopath/src/github.com/rancher/external-lb

This file was deleted.

26 changes: 13 additions & 13 deletions healthcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,30 @@ import (
)

var (
router = mux.NewRouter()
healtcheckPort = ":1000"
router = mux.NewRouter()
healthcheckPort = ":1000"
)

func startHealthcheck() {
router.HandleFunc("/", healtcheck).Methods("GET", "HEAD").Name("Healthcheck")
logrus.Info("Healthcheck handler is listening on ", healtcheckPort)
logrus.Fatal(http.ListenAndServe(healtcheckPort, router))
router.HandleFunc("/", healthcheck).Methods("GET", "HEAD").Name("Healthcheck")
logrus.Info("Healthcheck handler is listening on ", healthcheckPort)
logrus.Fatal(http.ListenAndServe(healthcheckPort, router))
}

func healtcheck(w http.ResponseWriter, req *http.Request) {
func healthcheck(w http.ResponseWriter, req *http.Request) {
// 1) test metadata server
_, err := m.MetadataClient.GetSelfStack()
if err != nil {
logrus.Error("Healtcheck failed: unable to reach metadata")
logrus.Error("Healthcheck failed: unable to reach metadata")
http.Error(w, "Failed to reach metadata server", http.StatusInternalServerError)
} else {
/* 2) test provider
_, err := provider.GetRecords()
if err != nil {
logrus.Error("Healtcheck failed: unable to reach a provider")
// 2) test provider
ok, err := provider.TestConnection()
if !ok {
logrus.Errorf("Healthcheck failed: unable to reach a provider, error:%v", err)
http.Error(w, "Failed to reach an external provider ", http.StatusInternalServerError)
} else {*/
} else {
w.Write([]byte("OK"))
//}
}
}
}
16 changes: 8 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,18 @@ func main() {

if update {
// get records from metadata
metadataRecs, err := m.GetMetadataLBRecords()
logrus.Debugf("Reading metadata LB Configs")
metadataLBConfigs, err := m.GetMetadataLBConfigs()
if err != nil {
logrus.Errorf("Error reading external dns entries: %v", err)
logrus.Errorf("Error reading metadata lb entries: %v", err)
}
logrus.Debugf("LB records from metadata: %v", metadataRecs)
logrus.Debugf("LB configs from metadata: %v", metadataLBConfigs)

/*update provider*/
for _, lbRec := range metadataRecs {
err := provider.ConfigureLBRecord(lbRec)
if err != nil {
logrus.Errorf("Failed to update provider with new LB record: %v", err)
}
logrus.Debugf("Reading Provider LB Configs")
err = UpdateProviderLBConfigs(metadataLBConfigs)
if err != nil {
logrus.Errorf("Error reading provider lb entries: %v", err)
}
lastUpdated = time.Now()
}
Expand Down
40 changes: 20 additions & 20 deletions metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"github.com/Sirupsen/logrus"
"github.com/rancher/external-lb/model"
"github.com/rancher/go-rancher-metadata/metadata"
"time"
"strings"
"time"
)

const (
Expand Down Expand Up @@ -55,37 +55,37 @@ func (m *MetadataClient) GetVersion() (string, error) {
return m.MetadataClient.GetVersion()
}

func (m *MetadataClient) GetMetadataLBRecords() (map[string]model.LBRecord, error) {
lbRecords := make(map[string]model.LBRecord)
func (m *MetadataClient) GetMetadataLBConfigs() (map[string]model.LBConfig, error) {
lbConfigs := make(map[string]model.LBConfig)

services, err := m.MetadataClient.GetServices()

if err != nil {
logrus.Infof("Error reading services %v", err)
} else {
for _, service := range services {
vip, ok := service.Labels["io.rancher.service.external_lb_vip"]
lb_endpoint, ok := service.Labels["io.rancher.service.external_lb_endpoint"]
if ok {
//label exists, configure external LB
logrus.Debugf("label exists for service : %v", service)
lbRecord := model.LBRecord{}
lbRecord.Vip = vip
lbRecord.ServiceName = service.Name
err = m.getContainerLBNodes(&lbRecord, service)
lbConfig := model.LBConfig{}
lbConfig.LBEndpoint = lb_endpoint
lbConfig.LBTargetName = service.StackName + "." + service.Name + "_rancher.internal"
err = m.getContainerLBTargets(&lbConfig, service)
if err != nil {
continue
}
lbRecords[service.Name] = lbRecord
lbConfigs[lb_endpoint] = lbConfig
} else {
continue
}
}
}
return lbRecords, nil

return lbConfigs, nil
}

func (m *MetadataClient) getContainerLBNodes(lbRecord *model.LBRecord, service metadata.Service) error {
func (m *MetadataClient) getContainerLBTargets(lbConfig *model.LBConfig, service metadata.Service) error {
containers := service.Containers

for _, container := range containers {
Expand All @@ -105,18 +105,18 @@ func (m *MetadataClient) getContainerLBNodes(lbRecord *model.LBRecord, service m
if len(container.Ports) == 0 {
continue
}

//split the container.Ports to get the publicip:port
portspec := strings.Split(container.Ports[0], ":")

if len(portspec) > 2 {
ip := portspec[0]
port := portspec[1]
lbNode := model.LBNode{}
lbNode.HostIP = ip
lbNode.Port = port
lbRecord.Nodes = append(lbRecord.Nodes, lbNode)

lbTarget := model.LBTarget{}
lbTarget.HostIP = ip
lbTarget.Port = port
lbConfig.LBTargets = append(lbConfig.LBTargets, lbTarget)
} else {
logrus.Debugf("Skipping container, PortSpec for container does not have host_ip:public_port:private:port format, container: %s, service: %s, ports: %s ", container.Name, container.ServiceName, container.Ports)
}
Expand Down
20 changes: 8 additions & 12 deletions model/lb.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package model

import (
)


type LBRecord struct {
Vip string
ServiceName string
Nodes []LBNode
type LBConfig struct {
LBEndpoint string
LBTargetName string
LBTargets []LBTarget
}

type LBNode struct {
HostIP string
Port string
}
type LBTarget struct {
HostIP string
Port string
}
6 changes: 3 additions & 3 deletions packaging/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ FROM alpine:3.2
MAINTAINER Rancher Labs, Inc.
RUN apk add --update ca-certificates

ENV EXT_DNS_RELEASE v0.0.1
ADD https://github.com/rancher/external-lb/releases/download/${EXT_DNS_RELEASE}/external-lb.tar.gz /external-lb.tar.gz
RUN tar -zxvf /external-lb.tar.gz -C /usr/bin
ENV EXT_DNS_RELEASE v0.1.0
ADD external-lb /usr/bin/external-lb


ENTRYPOINT ["/usr/bin/external-lb"]
12 changes: 5 additions & 7 deletions providers/external_lb_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,17 @@ import (

type Provider interface {
GetName() string
ConfigureLBRecord(model.LBRecord) error
AddLBConfig(config model.LBConfig) error
RemoveLBConfig(config model.LBConfig) error
UpdateLBConfig(config model.LBConfig) error
GetLBConfigs() ([]model.LBConfig, error)
TestConnection() (bool, error)
}

var (
providers map[string]Provider
)

func init() {
// try to resolve rancher-metadata before going further
// the resolution indicates that the network has been set

}

func GetProvider(name string) Provider {
if provider, ok := providers[name]; ok {
return provider
Expand Down
Loading

0 comments on commit 4d1a065

Please sign in to comment.