func registerService(s *ServerState, hostConfig *HostConfig) { extractedIPs := make([]*route53.ResourceRecord, 0) var extractIPs func(*etcdClient.Node) extractIPs = func(node *etcdClient.Node) { if node.Dir { if utils.MatchPathPrefix(node.Key, hostConfig.key) { for _, n := range node.Nodes { extractIPs(n) } } } else { if utils.MatchPath(node.Key, hostConfig.key) { extractedIPs = append(extractedIPs, &route53.ResourceRecord{ Value: aws.String(node.Value), }) } } } resp, err := s.etcdAPI.Get(context.Background(), utils.PrefixForPattern(hostConfig.key), &etcdClient.GetOptions{ Recursive: true, }) if err != nil { fmt.Printf("Key not found %s\n", utils.PrefixForPattern(hostConfig.key)) return } extractIPs(resp.Node) _, err = s.route53.ChangeResourceRecordSets(&route53.ChangeResourceRecordSetsInput{ ChangeBatch: &route53.ChangeBatch{ Changes: []*route53.Change{ { Action: aws.String(route53.ChangeActionUpsert), ResourceRecordSet: &route53.ResourceRecordSet{ Name: aws.String(hostConfig.domain), Type: aws.String(route53.RRTypeA), TTL: aws.Int64(1), ResourceRecords: extractedIPs, }, }, }, }, HostedZoneId: aws.String(hostConfig.zoneId), }) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) } }
func watchNewHostPath(s *ServerState, prefix string) { resp, err := s.etcdAPI.Get(context.Background(), prefix, &etcdClient.GetOptions{ Recursive: true, }) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } var watchPrefix = "" s.monitoredHosts = make([]*HostConfig, 0) for _, zone := range resp.Node.Nodes { zoneId := zone.Key[len(prefix):] zonePrefix := zone.Key + "/" fmt.Printf("Zone %s\n", zoneId) for _, domain := range zone.Nodes { domainName := domain.Key[len(zonePrefix):] fmt.Printf(" Register domain: %s\n", domainName) s.monitoredHosts = append(s.monitoredHosts, &HostConfig{ zoneId: zoneId, domain: domainName, key: domain.Value, }) if watchPrefix == "" { watchPrefix = domain.Value } else { watchPrefix = utils.CommonPrefixForPatterns(watchPrefix, domain.Value) } } } for _, host := range s.monitoredHosts { registerService(s, host) } fmt.Printf("Start watching prefix %s\n", watchPrefix) watcher := s.etcdAPI.Watcher(watchPrefix, &etcdClient.WatcherOptions{ AfterIndex: 0, Recursive: true, }) s.activeWatcher = &watcher for { resp, err = watcher.Next(context.Background()) if &watcher != s.activeWatcher { break } if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } for _, h := range s.monitoredHosts { // TODO expired? switch resp.Action { case "delete": if !utils.MatchPathPrefix(resp.Node.Key, h.key) { continue } case "set": if !utils.MatchPath(resp.Node.Key, h.key) { continue } if resp.PrevNode != nil && resp.Node.Value == resp.PrevNode.Value { fmt.Printf("Nothing changed\n") continue } default: continue } fmt.Printf("Matched update %s%s/%s\n", prefix, h.zoneId, h.domain) s.hostReloadCh <- h } } }