dependency/catalog_datacenters.go
func (d *CatalogDatacentersQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) {
	opts = opts.Merge(&QueryOptions{})

	log.Printf("[TRACE] %s: GET %s", d, &url.URL{
		Path:     "/v1/catalog/datacenters",
		RawQuery: opts.String(),
	})

	// This is pretty ghetto, but the datacenters endpoint does not support
	// blocking queries, so we are going to "fake it until we make it". When we
	// first query, the LastIndex will be "0", meaning we should immediately
	// return data, but future calls will include a LastIndex. If we have a
	// LastIndex in the query metadata, sleep for 15 seconds before asking Consul
	// again.
	//
	// This is probably okay given the frequency in which datacenters actually
	// change, but is technically not edge-triggering.
	if opts.WaitIndex != 0 {
		log.Printf("[TRACE] %s: long polling for %s", d, CatalogDatacentersQuerySleepTime)

		select {
		case <-d.stopCh:
			return nil, nil, ErrStopped
		case <-time.After(CatalogDatacentersQuerySleepTime):
		}
	}

	result, err := clients.Consul().Catalog().Datacenters()
	if err != nil {
		return nil, nil, errors.Wrapf(err, d.String())
	}

	// If the user opted in for skipping "down" datacenters, figure out which
	// datacenters are down.
	if d.ignoreFailing {
		dcs := make([]string, 0, len(result))
		for _, dc := range result {
			if _, _, err := clients.Consul().Catalog().Services(&api.QueryOptions{
				Datacenter:        dc,
				AllowStale:        false,
				RequireConsistent: true,
			}); err == nil {
				dcs = append(dcs, dc)
			}
		}
		result = dcs
	}

	log.Printf("[TRACE] %s: returned %d results", d, len(result))

	sort.Strings(result)

	return respWithMetadata(result)
}
func (d *CatalogDatacentersQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) {
	opts = opts.Merge(&QueryOptions{})

	log.Printf("[TRACE] %s: GET %s", d, &url.URL{
		Path:     "/v1/catalog/datacenters",
		RawQuery: opts.String(),
	})

	// This is pretty ghetto, but the datacenters endpoint does not support
	// blocking queries, so we are going to "fake it until we make it". When we
	// first query, the LastIndex will be "0", meaning we should immediately
	// return data, but future calls will include a LastIndex. If we have a
	// LastIndex in the query metadata, sleep for 15 seconds before asking Consul
	// again.
	//
	// This is probably okay given the frequency in which datacenters actually
	// change, but is technically not edge-triggering.
	if opts.WaitIndex != 0 {
		log.Printf("[TRACE] %s: long polling for %s", d, CatalogDatacentersQuerySleepTime)

		select {
		case <-d.stopCh:
			return nil, nil, ErrStopped
		case <-time.After(CatalogDatacentersQuerySleepTime):
		}
	}

	result, err := clients.Consul().Catalog().Datacenters()
	if err != nil {
		return nil, nil, errors.Wrapf(err, d.String())
	}

	// If the user opted in for skipping "down" datacenters, figure out which
	// datacenters are down.
	if d.ignoreFailing {
		dcs := make([]string, 0, len(result))
		for _, dc := range result {
			if _, _, err := clients.Consul().Catalog().Services(&api.QueryOptions{
				Datacenter:        dc,
				AllowStale:        false,
				RequireConsistent: true,
			}); err == nil {
				dcs = append(dcs, dc)
			}
		}
		result = dcs
	}

	log.Printf("[TRACE] %s: returned %d results", d, len(result))

	sort.Strings(result)

	return respWithMetadata(result)
}
// Fetch queries the Consul API defined by the given client and returns a slice
// of strings representing the datacenters