示例#1
0
func Init(docker *goDocker.Client, newContChan chan<- goDocker.Container, removeContChan chan<- string, drawStatsChan chan<- StatsMsg) {

	dockerEventChan = make(chan *goDocker.APIEvents, 10)
	statsResultsChan = make(chan StatsResult)
	statsResultsDoneChan = make(chan string)

	dockerClient = docker

	err := docker.AddEventListener(dockerEventChan)
	if err != nil {
		panic("Failed to add event listener: " + err.Error())
	}

	go statsRenderingRoutine(drawStatsChan)

	go dockerEventRoutingRoutine(dockerEventChan, newContChan, removeContChan)

	containers, _ := dockerClient.ListContainers(goDocker.ListContainersOptions{})
	Info.Println("Listing intial", len(containers), "containers as started")
	for _, cont := range containers {
		Info.Println("Marking", cont.ID, "as started")
		dockerEventChan <- &goDocker.APIEvents{ID: cont.ID, Status: "start"}
		//startedContainerChan <- cont.ID
	}

}
// RegisterDockerEventListener registers function as event listener with docker.
// laziness defines how many seconds to wait, after an event is received, until a refresh is triggered
func RegisterDockerEventListener(client *docker.Client, function func(), wg *sync.WaitGroup, laziness int) {
	wg.Add(1)
	defer wg.Done()

	events := make(chan *docker.APIEvents)
	defer close(events)

	err := client.AddEventListener((chan<- *docker.APIEvents)(events))
	if err != nil {
		log.Fatalf("Unable to add docker event listener: %s", err)
	}
	defer client.RemoveEventListener(events)

	log.Info("Listening to docker events...")
	for {
		event := <-events

		if event == nil {
			continue
		}

		if event.Status == "start" || event.Status == "stop" || event.Status == "die" {
			log.Debug("Received event %s for container %s", event.Status, event.ID[:12])

			Refresh.Mu.Lock()
			if !Refresh.IsTriggered {
				log.Info("Triggering refresh in %d seconds", laziness)
				Refresh.timer = time.AfterFunc(time.Duration(laziness)*time.Second, function)
				Refresh.IsTriggered = true
			}
			Refresh.Mu.Unlock()
		}
	}
}
func main() {
	logger = log.New(os.Stdout, "logger: ", log.Lshortfile|log.Ldate|log.Ltime)
	var VERSION = os.Getenv("CCP_VERSION")

	logger.Println("dnsbridgeserver " + VERSION + ": starting")

	getEnvVars()

	var dockerConnected = false
	var tries = 0
	var docker *dockerapi.Client
	var err error
	for tries = 0; tries < MAX_TRIES; tries++ {
		docker, err = dockerapi.NewClient(DOCKER_URL)
		err = docker.Ping()
		if err != nil {
			logger.Println("could not ping docker host")
			logger.Println("sleeping and will retry in %d sec\n", delaySeconds)
			time.Sleep(delay)
		} else {
			logger.Println("no err in connecting to docker")
			dockerConnected = true
			break
		}
	}

	if dockerConnected == false {
		logger.Println("failing, could not connect to docker after retries")
		panic("cant connect to docker")
	}

	events := make(chan *dockerapi.APIEvents)
	assert(docker.AddEventListener(events))
	logger.Println("dnsbridgeserver: Listening for Docker events...")
	for msg := range events {
		switch msg.Status {
		//case "start", "create":
		case "start":
			logger.Println("event: " + msg.Status + " ID=" + msg.ID + " From:" + msg.From)
			dnsbridgeapi.Action(logger, msg.Status, msg.ID, docker, TTL, CONSUL_URL, DOMAIN)
		case "stop":
			logger.Println("event: " + msg.Status + " ID=" + msg.ID + " From:" + msg.From)
			dnsbridgeapi.Action(logger, msg.Status, msg.ID, docker, TTL, CONSUL_URL, DOMAIN)
		case "destroy":
			logger.Println("event: " + msg.Status + " ID=" + msg.ID + " From:" + msg.From)
			dnsbridgeapi.Action(logger, msg.Status, msg.ID, docker, TTL, CONSUL_URL, DOMAIN)
		case "die":
			logger.Println("event: " + msg.Status + " ID=" + msg.ID + " From:" + msg.From)
		default:
			logger.Println("event: " + msg.Status)
		}
	}

}
示例#4
0
文件: pool.go 项目: bitrun/api
func RunPool(config *Config, client *docker.Client) {
	chEvents := make(chan *docker.APIEvents)
	pools = make(map[string]*Pool)

	// Setup docker event listener
	if err := client.AddEventListener(chEvents); err != nil {
		log.Fatalln(err)
	}

	go func() {
		for {
			event := <-chEvents
			if event == nil {
				continue
			}

			if event.Status == "die" {
				for _, pool := range pools {
					if pool.Exists(event.ID) {
						log.Println("pool's container got destroyed:", event.ID)
						pool.Remove(event.ID)
					}
				}
			}
		}
	}()

	for _, cfg := range config.Pools {
		if cfg.Capacity < 1 {
			continue
		}

		log.Println("initializing pool for:", cfg.Image)

		pool, err := NewPool(config, client, cfg.Image, cfg.Capacity, cfg.Standby)
		if err != nil {
			log.Fatalln(err)
		}

		err = pool.Load()
		if err != nil {
			log.Fatalln(err)
		}

		go pool.Monitor()
		pools[cfg.Image] = pool
	}
}
示例#5
0
func generateFromEvents(client *docker.Client, configs ConfigFile) {
	configs = configs.filterWatches()
	if len(configs.Config) == 0 {
		return
	}

	wg.Add(1)
	defer wg.Done()

	for {
		if client == nil {
			var err error
			endpoint, err := getEndpoint()
			if err != nil {
				log.Printf("Bad endpoint: %s", err)
				time.Sleep(10 * time.Second)
				continue
			}

			client, err = NewDockerClient(endpoint)
			if err != nil {
				log.Printf("Unable to connect to docker daemon: %s", err)
				time.Sleep(10 * time.Second)
				continue
			}
			generateFromContainers(client)
		}

		eventChan := make(chan *docker.APIEvents, 100)
		defer close(eventChan)

		watching := false
		for {

			if client == nil {
				break
			}
			err := client.Ping()
			if err != nil {
				log.Printf("Unable to ping docker daemon: %s", err)
				if watching {
					client.RemoveEventListener(eventChan)
					watching = false
					client = nil
				}
				time.Sleep(10 * time.Second)
				break

			}

			if !watching {
				err = client.AddEventListener(eventChan)
				if err != nil && err != docker.ErrListenerAlreadyExists {
					log.Printf("Error registering docker event listener: %s", err)
					time.Sleep(10 * time.Second)
					continue
				}
				watching = true
				log.Println("Watching docker events")
			}

			select {

			case event := <-eventChan:
				if event == nil {
					if watching {
						client.RemoveEventListener(eventChan)
						watching = false
						client = nil
					}
					break
				}

				if event.Status == "start" || event.Status == "stop" || event.Status == "die" {
					log.Printf("Received event %s for container %s", event.Status, event.ID[:12])
					generateFromContainers(client)
				}
			case <-time.After(10 * time.Second):
				// check for docker liveness
			}

		}
	}
}
示例#6
0
文件: main.go 项目: raceli/resolvable
func registerContainers(docker *dockerapi.Client, events chan *dockerapi.APIEvents, dns resolver.Resolver, containerDomain string, hostIP net.IP) error {
	// TODO add an options struct instead of passing all as parameters
	// though passing the events channel from an options struct was triggering
	// data race warnings within AddEventListener, so needs more investigation

	if events == nil {
		events = make(chan *dockerapi.APIEvents)
	}
	if err := docker.AddEventListener(events); err != nil {
		return err
	}

	if !strings.HasPrefix(containerDomain, ".") {
		containerDomain = "." + containerDomain
	}

	getAddress := func(container *dockerapi.Container) (net.IP, error) {
		for {
			if container.NetworkSettings.IPAddress != "" {
				return net.ParseIP(container.NetworkSettings.IPAddress), nil
			}

			if container.HostConfig.NetworkMode == "host" {
				if hostIP == nil {
					return nil, errors.New("IP not available with network mode \"host\"")
				} else {
					return hostIP, nil
				}
			}

			if strings.HasPrefix(container.HostConfig.NetworkMode, "container:") {
				otherId := container.HostConfig.NetworkMode[len("container:"):]
				var err error
				container, err = docker.InspectContainer(otherId)
				if err != nil {
					return nil, err
				}
				continue
			}

			return nil, fmt.Errorf("unknown network mode", container.HostConfig.NetworkMode)
		}
	}

	addContainer := func(containerId string) error {
		container, err := docker.InspectContainer(containerId)
		if err != nil {
			return err
		}
		addr, err := getAddress(container)
		if err != nil {
			return err
		}

		err = dns.AddHost(containerId, addr, container.Config.Hostname, container.Name[1:]+containerDomain)
		if err != nil {
			return err
		}

		env := parseContainerEnv(container.Config.Env, "DNS_")
		if dnsDomains, ok := env["DNS_RESOLVES"]; ok {
			if dnsDomains == "" {
				return errors.New("empty DNS_RESOLVES, should contain a comma-separated list with at least one domain")
			}

			port := 53
			if portString := env["DNS_PORT"]; portString != "" {
				port, err = strconv.Atoi(portString)
				if err != nil {
					return errors.New("invalid DNS_PORT \"" + portString + "\", should contain a number")
				}
			}

			domains := strings.Split(dnsDomains, ",")
			err = dns.AddUpstream(containerId, addr, port, domains...)
			if err != nil {
				return err
			}
		}

		if bridge := container.NetworkSettings.Bridge; bridge != "" {
			bridgeAddr := net.ParseIP(container.NetworkSettings.Gateway)
			err = dns.AddHost("bridge:"+bridge, bridgeAddr, bridge)
			if err != nil {
				return err
			}
		}

		return nil
	}

	containers, err := docker.ListContainers(dockerapi.ListContainersOptions{})
	if err != nil {
		return err
	}

	for _, listing := range containers {
		if err := addContainer(listing.ID); err != nil {
			log.Printf("error adding container %s: %s\n", listing.ID[:12], err)
		}
	}

	if err = dns.Listen(); err != nil {
		return err
	}
	defer dns.Close()

	for msg := range events {
		go func(msg *dockerapi.APIEvents) {
			switch msg.Status {
			case "start":
				if err := addContainer(msg.ID); err != nil {
					log.Printf("error adding container %s: %s\n", msg.ID[:12], err)
				}
			case "die":
				dns.RemoveHost(msg.ID)
				dns.RemoveUpstream(msg.ID)
			}
		}(msg)
	}

	return errors.New("docker event loop closed")
}