func (flipper *HAProxyFlipperClient) Orchestrate(switchEvent types.MasterSwitchedEvent) { flipper.lock.Lock() defer flipper.lock.Unlock() logger.NoteWorthy.Printf("Redis cluster {%s} master failover detected from {%s}:{%d} to {%s}:{%d}.", switchEvent.Name, switchEvent.OldMasterIp, switchEvent.OldMasterPort, switchEvent.NewMasterIp, switchEvent.NewMasterPort) logger.NoteWorthy.Printf("Master Switched : %s", util.String(switchEvent)) configuration := flipper.configurationManager.GetCurrentConfiguration() logger.Info.Printf("Current Configuration : %s", util.String(configuration.Clusters)) cluster, err := configuration.FindClusterByName(switchEvent.Name) if err != nil { logger.Error.Printf("Redis cluster called %s not found in configuration.", switchEvent.Name) return } logger.Info.Printf("Cluster found : %s", util.String(cluster)) detail := &types.MasterDetails{ ExternalPort: cluster.ExternalPort, Name: switchEvent.Name, Ip: switchEvent.NewMasterIp, Port: switchEvent.NewMasterPort} flipper.state.AddOrReplace(detail) flipper.renderAndReload(configuration, flipper.state) }
func TestCanMarkSentinelsDown(t *testing.T) { state := NewSentinelState(func(_ types.Sentinel) {}) sentinel := types.Sentinel{Host: "10.1.1.2", Port: 12345} sentinelAddedMessage := &SentinelAdded{Sentinel: sentinel} sentinelLostMessage := &SentinelLost{Sentinel: sentinel} responseChannel := make(chan SentinelTopology) state.Notify(sentinelAddedMessage) state.Notify(sentinelLostMessage) state.GetState(TopologyRequest{ReplyChannel: responseChannel}) topologyState := <-responseChannel fmt.Print(util.String(topologyState)) if len(topologyState.Sentinels) != 1 { t.Error("Topology count should be 1") } sen, _ := topologyState.FindSentinelInfo(sentinel) if sen.SentinelLocation != sentinel.GetLocation() { t.Error("Wrong host found") } if sen.State != SentinelMarkedDown { t.Errorf("Sentinel in wrong state : %d", sen.State) } }
func (c *ConsulFlipperClient) InitialiseRunningState(state *types.MasterDetailsCollection) { logger.Info.Printf("InitialiseRunningState called : %s", util.String(state.Items())) for _, md := range state.Items() { c.UpdateConsul(md.Name, md.Ip, md.Port) } }
func TestSerialisationOnNewMasterDetailsCollection(t *testing.T) { collection := NewMasterDetailsCollection() detail1 := &MasterDetails{ExternalPort: 1111, Name: "a", Ip: "1.1.1.1.", Port: 2222} detail2 := &MasterDetails{ExternalPort: 2222, Name: "b", Ip: "2.2.2.2.", Port: 3333} detail3 := &MasterDetails{ExternalPort: 2222, Name: "c", Ip: "2.2.2.2.", Port: 3333} collection.AddOrReplace(detail3) collection.AddOrReplace(detail2) collection.AddOrReplace(detail1) json := util.String(collection.Items()) if json == "{}" { t.Errorf("Json should not be empty : %s", json) } }
func renderTemplate(details *types.MasterDetailsCollection, outputPath string, templatepath string) (bool, error) { logger.Info.Printf("Details %s", util.String(details.Items())) renderedTemplate, err := template.RenderTemplate(templatepath, details) if err != nil { logger.Error.Printf("Error rendering tempate at %s.", templatepath) return false, err } if util.FileExists(outputPath) { newFileHash := util.HashString(renderedTemplate) oldFileHash, err := util.HashFile(outputPath) if err != nil { logger.Error.Printf("Error hashing existing HAProxy config file at %s.", outputPath) return false, err } if newFileHash == oldFileHash { logger.NoteWorthy.Printf("Existing config file up todate. New file hash : %s == Old file hash %s. Nothing to do.", newFileHash, oldFileHash) return true, nil } logger.Info.Printf("Updating config file. New file hash : %s != Old file hash %s", newFileHash, oldFileHash) } err = util.WriteFile(outputPath, renderedTemplate) if err != nil { logger.Error.Printf("Error writing file to %s : %s\n", outputPath, err.Error()) return false, err } return true, nil }
func (s SentinelState) updateState(event interface{}) { switch e := event.(type) { case *SentinelAdded: sentinel := e.GetSentinel() uid := s.state.createKey(sentinel) //if we don't know about the sentinel start monitoring it if _, exists := s.state.Sentinels[uid]; !exists { info := &SentinelInfo{SentinelLocation: uid, LastUpdated: time.Now().UTC(), State: SentinelMarkedUp} s.state.Sentinels[uid] = info go s.startMonitoringSentinel(sentinel) logger.Trace.Printf("Sentinel added : %s", util.String(sentinel)) } case *SentinelLost: sentinel := e.GetSentinel() uid := s.state.createKey(sentinel) currentInfo, ok := s.state.Sentinels[uid] if ok { currentInfo.LastUpdated = time.Now().UTC() if currentInfo.State != SentinelMarkedDown { currentInfo.State = SentinelMarkedDown util.Schedule(func() { go s.startMonitoringSentinel(sentinel) }, SentinelReconnectionPeriod) logger.Trace.Printf("Sentinel lost : %s", util.String(sentinel)) logger.Trace.Printf("Sentinel state : %s", util.String(s.state)) } } else { logger.Trace.Printf("Unknown sentinel lost : %s.", util.String(sentinel)) } case *SentinelPing: sentinel := e.GetSentinel() uid := s.state.createKey(sentinel) currentInfo, exists := s.state.Sentinels[uid] if exists { if currentInfo.State != SentinelMarkedAlive { currentInfo.State = SentinelMarkedAlive logger.Trace.Printf("Sentinel ping : %s", util.String(sentinel)) logger.Trace.Printf("Sentinel state : %s.", util.String(s.state)) } currentInfo.LastUpdated = time.Now().UTC() } else { logger.Trace.Printf("Unknown sentinel ping : %s.", util.String(sentinel)) } case *SentinelUnknown: sentinel := e.GetSentinel() uid := s.state.createKey(sentinel) currentInfo, exists := s.state.Sentinels[uid] if exists { currentInfo.State = SentinelMarkedUnknown currentInfo.LastUpdated = time.Now().UTC() } else { logger.Trace.Printf("Unknown sentinel unknown{*} : %s.", util.String(sentinel)) } case *SentinelClustersMonitoredUpdate: sentinel := e.GetSentinel() uid := s.state.createKey(sentinel) if info, exists := s.state.Sentinels[uid]; exists { info.Clusters = e.Clusters } else { logger.Trace.Printf("Unknown sentinel updated state : %s.", util.String(sentinel)) } default: logger.Error.Println("Unknown sentinel event : ", util.String(e)) } }
func (c *ConsulFlipperClient) Orchestrate(switchEvent types.MasterSwitchedEvent) { logger.NoteWorthy.Printf("Redis master changed : %s", util.String(switchEvent)) c.UpdateConsul(switchEvent.Name, switchEvent.NewMasterIp, switchEvent.NewMasterPort) }
func (*NoOpFlipperClient) Orchestrate(switchEvent types.MasterSwitchedEvent) { logger.NoteWorthy.Printf("Orchestrate called : %s", util.String(switchEvent)) }
func (*NoOpFlipperClient) InitialiseRunningState(state *types.MasterDetailsCollection) { logger.NoteWorthy.Printf("InitialiseRunningState called : %s", util.String(state.Items())) }