func (r *Reporter) Stop() {
	close(r.abort)
	<-r.exit
}
Stop stops the reporter. It will block until it actually stops (i.e. there's
no need to call Wait after calling Stop).
package status
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"sync"
	"time"
	"github.com/ajg/form"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/tsuru/bs/bslog"
	"github.com/tsuru/bs/container"
	node "github.com/tsuru/bs/node"
	"github.com/tsuru/tsuru/provision"
)
type containerStatus struct {
	ID     string
	Name   string
	Status string
}
type respUnit struct {
	ID    string
	Found bool
}
type ReporterConfig struct {
	Interval       time.Duration
	DockerEndpoint string
	TsuruEndpoint  string
	TsuruToken     string
	Kubernetes     bool
}
type Reporter struct {
	config     *ReporterConfig
	abort      chan<- struct{}
	exit       <-chan struct{}
	checks     *checkCollection
	addrs      []string
	infoClient *container.InfoClient
	httpClient *http.Client
	mu         sync.Mutex
	removeMap  map[string]chan struct{}
}
type hostStatus struct {
	Addrs  []string
	Units  []containerStatus
	Checks []hostCheckResult
}
const (
	dialTimeout = 10 * time.Second
	fullTimeout = 1 * time.Minute
)
var errRouteNotFound = errors.New("route not found")
func NewReporter(config *ReporterConfig) (*Reporter, error) {
	if config.TsuruEndpoint == "" {
		return nil, errors.New("tsuru endpoint must be set for status reporting")
	}
	abort := make(chan struct{})
	exit := make(chan struct{})
	infoClient, err := container.NewClient(config.DockerEndpoint)
	if err != nil {
		return nil, err
	}
	checks := NewCheckCollection(infoClient.GetClient())
	addrs, err := node.GetNodeAddrs()
	if err != nil {
		return nil, fmt.Errorf("[status reporter] unable to get network addresses: %s", err)
	}
	transport := http.Transport{
		Dial: (&net.Dialer{
			Timeout:   dialTimeout,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: dialTimeout,
		IdleConnTimeout:     30 * time.Second,
	}
	reporter := Reporter{
		config:     config,
		abort:      abort,
		exit:       exit,
		infoClient: infoClient,
		checks:     checks,
		addrs:      addrs,
		httpClient: &http.Client{
			Transport: &transport,
			Timeout:   fullTimeout,
		},
		removeMap: make(map[string]chan struct{}),
	}
	go func(abort <-chan struct{}) {
		for {
			reporter.reportStatus()
			select {
			case <-abort:
				close(exit)
				return
			case <-time.After(reporter.config.Interval):
			}
		}
	}(abort)
	return &reporter, nil
}