Beispiel #1
0
func main() {
	numProcs := runtime.NumCPU() * 2
	runtime.GOMAXPROCS(numProcs)
	numWorkers := numProcs * 4
	c := getCfr()
	workCh := make(chan *cfr.Distribution)
	wg := sync.WaitGroup{}
	wg.Add(numWorkers)
	log.Debugf("Spawning %v workers", numWorkers)
	for i := 0; i < numWorkers; i++ {
		go work(c, workCh, &wg)
	}
	dists, err := cfr.ListDistributions(c)
	if err != nil {
		log.Fatalf("Error listing distributions: %v", err)
		return
	}
	for _, dist := range dists {
		workCh <- dist
	}
	// Signal end of work
	for i := 0; i < numWorkers; i++ {
		workCh <- nil
	}
	wg.Wait()
	log.Debug("cfrjanitor done.")
}
Beispiel #2
0
// loadHosts loads the initial list of hosts based on the existing entries in
// the CDN and DNS services we manage
func loadHosts() (map[string]*host, error) {

	log.Debug("Loading existing CloudFlare records ...")
	cflRecs, err := cflutil.GetAllRecords()
	if err != nil {
		return nil, fmt.Errorf("Unable to load Cloudflare records: %v", err)
	}
	log.Debugf("Loaded %d existing Cloudflare records", len(cflRecs))

	log.Debug("Loading existing DNSimple records ...")
	dspRecs, err := dsputil.GetAllRecords()
	if err != nil {
		return nil, fmt.Errorf("Unable to load DNSimple records: %v", err)
	}
	log.Debugf("Loaded %d existing DNSimple records", len(dspRecs))

	dists, err := cfr.ListDistributions(cfrutil)
	if err != nil {
		return nil, fmt.Errorf("Unable to load cloudfront distributions: %v", err)
	}
	log.Debugf("Loaded %d existing distributions", len(dists))

	// Collect round-robin entries in Cloudflare
	cflGroups := make(map[string]map[string]*cloudflare.Record, 0)
	addToCflGroup := func(name string, r cloudflare.Record) {
		log.Debugf("Adding to %v: %v", name, r.Value)
		g := cflGroups[name]
		if g == nil {
			g = make(map[string]*cloudflare.Record, 1)
			cflGroups[name] = g
		}
		g[r.Value] = &r
	}

	// Collect round-robin entries in DNSimple
	dspGroups := make(map[string]map[string]*dnsimple.Record, 0)
	addToDspGroup := func(name string, r dnsimple.Record) {
		log.Debugf("Adding to %v: %v", name, r.Content)
		g := dspGroups[name]
		if g == nil {
			g = make(map[string]*dnsimple.Record, 1)
			dspGroups[name] = g
		}
		g[r.Content] = &r
	}

	// Build map of existing hosts
	preHosts := make(map[string]*host)
	addHost := func(name string, ip string, cflRec *cloudflare.Record, dspRec *dnsimple.Record) {
		h := preHosts[ip]
		if h == nil {
			h = &host{name: name, ip: ip}
			preHosts[ip] = h
		}
		if cflRec != nil {
			h.cflRecord = cflRec
		}
		if dspRec != nil {
			h.dspRecord = dspRec
		}
	}

	// Look through Cloudflare records to find peers, fallbacks and groups
	for _, r := range cflRecs {
		if isFallback(r.Name) {
			log.Debugf("Adding fallback: %v", r.Name)
			addHost(r.Name, r.Value, &r, nil)
		} else if isPeer(r.Name) {
			log.Debugf("Not adding peer: %v", r.Name)
		} else if r.Name == RoundRobin {
			addToCflGroup(RoundRobin, r)
		} else if r.Name == Fallbacks {
			addToCflGroup(Fallbacks, r)
		} else if r.Name == Peers {
			addToCflGroup(Peers, r)
		} else if strings.HasSuffix(r.Name, ".fallbacks") {
			addToCflGroup(r.Name, r)
		} else {
			log.Tracef("Unrecognized Cloudflare record: %v", r.FullName)
		}
	}

	// Look through DNSimple records to find peers, fallbacks and groups
	for _, r := range dspRecs {
		if isFallback(r.Name) {
			log.Debugf("Adding fallback: %v", r.Name)
			addHost(r.Name, r.Content, nil, &r)
		} else if isPeer(r.Name) {
			log.Debugf("Not adding peer: %v", r.Name)
		} else if r.Name == RoundRobin {
			addToDspGroup(RoundRobin, r)
		} else if r.Name == Fallbacks {
			addToDspGroup(Fallbacks, r)
		} else if r.Name == Peers {
			addToDspGroup(Peers, r)
		} else if strings.HasSuffix(r.Name, ".fallbacks") {
			addToDspGroup(r.Name, r)
		} else {
			log.Tracef("Unrecognized DNSimple record: %v", r.Name)
		}
	}

	hostsByName := make(map[string]*host)
	hostsByIp := make(map[string]*host)
	for _, pre := range preHosts {
		h := newHost(pre.name, pre.ip, "", pre.cflRecord, pre.dspRecord)
		hostsByName[h.name] = h
		hostsByIp[h.ip] = h
	}

	for _, d := range dists {
		h, found := hostsByName[d.InstanceId]
		if found {
			h.cfrDist = d
		}
	}

	// Update hosts with Cloudflare group info
	for _, h := range hostsByIp {
		for _, hg := range h.cflGroups {
			g, found := cflGroups[hg.subdomain]
			if found {
				hg.existing = g[h.ip]
				delete(g, h.ip)
			}
		}
		// Don't accept round robins unless we have a working Cloudfront
		// distribution
		if h.cfrDistReady() {
			for _, hg := range h.dspGroups {
				g, found := dspGroups[hg.subdomain]
				if found {
					hg.existing = g[h.ip]
					delete(g, h.ip)
				}
			}
		}
	}

	var wg sync.WaitGroup

	// Remove items from rotation that don't have a corresponding host
	for k, g := range cflGroups {
		for _, r := range g {
			wg.Add(1)
			go removeCflRecord(&wg, k, r)
		}
	}
	for k, g := range dspGroups {
		for _, r := range g {
			wg.Add(1)
			go removeDspRecord(&wg, k, r)
		}
	}

	wg.Wait()

	// Start hosts
	for _, h := range hostsByIp {
		go h.run()
	}

	return hostsByIp, nil
}