// Main runs the app func appMain() { var ( window = flag.Duration("window", 15*time.Second, "window") listen = flag.String("http.address", ":"+strconv.Itoa(xfer.AppPort), "webserver listen address") logPrefix = flag.String("log.prefix", "<app>", "prefix for each log line") ) flag.Parse() if !strings.HasSuffix(*logPrefix, " ") { *logPrefix += " " } log.SetPrefix(*logPrefix) defer log.Print("app exiting") rand.Seed(time.Now().UnixNano()) app.UniqueID = strconv.FormatInt(rand.Int63(), 16) app.Version = version log.Printf("app starting, version %s, ID %s", app.Version, app.UniqueID) handler := router(app.NewCollector(*window)) go func() { log.Printf("listening on %s", *listen) log.Print(http.ListenAndServe(*listen, handler)) }() common.SignalHandlerLoop() }
func main() { var ( justVersion bool logLevel = "info" c proxy.Config withDNS bool ) c.Version = version mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit") mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)") mflagext.ListVar(&c.ListenAddrs, []string{"H"}, nil, "addresses on which to listen") mflag.StringVar(&c.HostnameFromLabel, []string{"-hostname-from-label"}, "", "Key of container label from which to obtain the container's hostname") mflag.StringVar(&c.HostnameMatch, []string{"-hostname-match"}, "(.*)", "Regexp pattern to apply on container names (e.g. '^aws-[0-9]+-(.*)$')") mflag.StringVar(&c.HostnameReplacement, []string{"-hostname-replacement"}, "$1", "Expression to generate hostnames based on matches from --hostname-match (e.g. 'my-app-$1')") mflag.BoolVar(&c.RewriteInspect, []string{"-rewrite-inspect"}, false, "Rewrite 'inspect' calls to return the weave network settings (if attached)") mflag.BoolVar(&c.NoDefaultIPAM, []string{"#-no-default-ipam", "-no-default-ipalloc"}, false, "do not automatically allocate addresses for containers without a WEAVE_CIDR") mflag.BoolVar(&c.NoRewriteHosts, []string{"-no-rewrite-hosts"}, false, "do not automatically rewrite /etc/hosts. Use if you need the docker IP to remain in /etc/hosts") mflag.StringVar(&c.TLSConfig.CACert, []string{"#tlscacert", "-tlscacert"}, "", "Trust certs signed only by this CA") mflag.StringVar(&c.TLSConfig.Cert, []string{"#tlscert", "-tlscert"}, "", "Path to TLS certificate file") mflag.BoolVar(&c.TLSConfig.Enabled, []string{"#tls", "-tls"}, false, "Use TLS; implied by --tlsverify") mflag.StringVar(&c.TLSConfig.Key, []string{"#tlskey", "-tlskey"}, "", "Path to TLS key file") mflag.BoolVar(&c.TLSConfig.Verify, []string{"#tlsverify", "-tlsverify"}, false, "Use TLS and verify the remote") mflag.BoolVar(&withDNS, []string{"#-with-dns", "#w"}, false, "option removed") mflag.BoolVar(&c.WithoutDNS, []string{"-without-dns"}, false, "instruct created containers to never use weaveDNS as their nameserver") mflag.BoolVar(&c.NoMulticastRoute, []string{"-no-multicast-route"}, false, "do not add a multicast route via the weave interface when attaching containers") mflag.Parse() if justVersion { fmt.Printf("weave proxy %s\n", version) os.Exit(0) } common.SetLogLevel(logLevel) Log.Infoln("weave proxy", version) Log.Infoln("Command line arguments:", strings.Join(os.Args[1:], " ")) if withDNS { Log.Warning("--with-dns option has been removed; DNS is on by default") } c.Image = getenv("EXEC_IMAGE", "weaveworks/weaveexec") c.DockerBridge = getenv("DOCKER_BRIDGE", "docker0") c.DockerHost = getenv("DOCKER_HOST", "unix:///var/run/docker.sock") p, err := proxy.NewProxy(c) if err != nil { Log.Fatalf("Could not start proxy: %s", err) } defer p.Stop() listeners := p.Listen() p.AttachExistingContainers() go p.Serve(listeners) go p.ListenAndServeStatus("/home/weave/status.sock") common.SignalHandlerLoop() }
// Main runs the app func appMain() { var ( window = flag.Duration("window", 15*time.Second, "window") listen = flag.String("http.address", ":"+strconv.Itoa(xfer.AppPort), "webserver listen address") logLevel = flag.String("log.level", "info", "logging threshold level: debug|info|warn|error|fatal|panic") logPrefix = flag.String("log.prefix", "<app>", "prefix for each log line") weaveAddr = flag.String("weave.addr", app.DefaultWeaveURL, "Address on which to contact WeaveDNS") weaveHostname = flag.String("weave.hostname", app.DefaultHostname, "Hostname to advertise in WeaveDNS") containerName = flag.String("container.name", app.DefaultContainerName, "Name of this container (to lookup container ID)") dockerEndpoint = flag.String("docker", app.DefaultDockerEndpoint, "Location of docker endpoint (to lookup container ID)") ) flag.Parse() setLogLevel(*logLevel) setLogFormatter(*logPrefix) defer log.Info("app exiting") // Start background version checking checkpoint.CheckInterval(&checkpoint.CheckParams{ Product: "scope-app", Version: app.Version, SignatureFile: signatureFile, }, versionCheckPeriod, func(r *checkpoint.CheckResponse, err error) { if r.Outdated { log.Infof("Scope version %s is available; please update at %s", r.CurrentVersion, r.CurrentDownloadURL) } }) rand.Seed(time.Now().UnixNano()) app.UniqueID = strconv.FormatInt(rand.Int63(), 16) app.Version = version log.Infof("app starting, version %s, ID %s", app.Version, app.UniqueID) // If user supplied a weave router address, periodically try and register // out IP address in WeaveDNS. if *weaveAddr != "" { weave, err := newWeavePublisher( *dockerEndpoint, *weaveAddr, *weaveHostname, *containerName) if err != nil { log.Println("Failed to start weave integration:", err) } else { defer weave.Stop() } } handler := router(app.NewCollector(*window)) go func() { log.Infof("listening on %s", *listen) log.Info(http.ListenAndServe(*listen, handler)) }() common.SignalHandlerLoop() }
// Main runs the probe func probeMain() { var ( targets = []string{fmt.Sprintf("localhost:%d", xfer.AppPort)} token = flag.String("token", "default-token", "probe token") httpListen = flag.String("http.listen", "", "listen address for HTTP profiling and instrumentation server") publishInterval = flag.Duration("publish.interval", 3*time.Second, "publish (output) interval") spyInterval = flag.Duration("spy.interval", time.Second, "spy (scan) interval") spyProcs = flag.Bool("processes", true, "report processes (needs root)") procRoot = flag.String("proc.root", "/proc", "location of the proc filesystem") useConntrack = flag.Bool("conntrack", true, "also use conntrack to track connections") insecure = flag.Bool("insecure", false, "(SSL) explicitly allow \"insecure\" SSL connections and transfers") logPrefix = flag.String("log.prefix", "<probe>", "prefix for each log line") logLevel = flag.String("log.level", "info", "logging threshold level: debug|info|warn|error|fatal|panic") dockerEnabled = flag.Bool("docker", false, "collect Docker-related attributes for processes") dockerInterval = flag.Duration("docker.interval", 10*time.Second, "how often to update Docker attributes") dockerBridge = flag.String("docker.bridge", "docker0", "the docker bridge name") kubernetesEnabled = flag.Bool("kubernetes", false, "collect kubernetes-related attributes for containers, should only be enabled on the master node") kubernetesAPI = flag.String("kubernetes.api", "", "Address of kubernetes master api") kubernetesInterval = flag.Duration("kubernetes.interval", 10*time.Second, "how often to do a full resync of the kubernetes data") weaveRouterAddr = flag.String("weave.router.addr", "127.0.0.1:6784", "IP address & port of the Weave router") weaveDNSTarget = flag.String("weave.hostname", fmt.Sprintf("scope.weave.local:%d", xfer.AppPort), "Hostname to lookup in weaveDNS") ) flag.Parse() setLogLevel(*logLevel) setLogFormatter(*logPrefix) // Setup in memory metrics sink inm := metrics.NewInmemSink(time.Minute, 2*time.Minute) sig := metrics.DefaultInmemSignal(inm) defer sig.Stop() metrics.NewGlobal(metrics.DefaultConfig("scope-probe"), inm) defer log.Info("probe exiting") if *spyProcs && os.Getegid() != 0 { log.Warn("-process=true, but that requires root to find everything") } rand.Seed(time.Now().UnixNano()) probeID := strconv.FormatInt(rand.Int63(), 16) var ( hostName = hostname.Get() hostID = hostName // TODO(pb): we should sanitize the hostname ) log.Infof("probe starting, version %s, ID %s", version, probeID) go check() if len(flag.Args()) > 0 { targets = flag.Args() } log.Infof("publishing to: %s", strings.Join(targets, ", ")) probeConfig := appclient.ProbeConfig{ Token: *token, ProbeID: probeID, Insecure: *insecure, } clients := appclient.NewMultiAppClient(func(hostname, endpoint string) (appclient.AppClient, error) { return appclient.NewAppClient( probeConfig, hostname, endpoint, xfer.ControlHandlerFunc(controls.HandleControlRequest), ) }) defer clients.Stop() resolver := appclient.NewResolver(targets, net.LookupIP, clients.Set) defer resolver.Stop() processCache := process.NewCachingWalker(process.NewWalker(*procRoot)) scanner := procspy.NewConnectionScanner(processCache) endpointReporter := endpoint.NewReporter(hostID, hostName, *spyProcs, *useConntrack, scanner) defer endpointReporter.Stop() p := probe.New(*spyInterval, *publishInterval, clients) p.AddTicker(processCache) p.AddReporter( endpointReporter, host.NewReporter(hostID, hostName), process.NewReporter(processCache, hostID, process.GetDeltaTotalJiffies), ) p.AddTagger(probe.NewTopologyTagger(), host.NewTagger(hostID, probeID)) if *dockerEnabled { if err := report.AddLocalBridge(*dockerBridge); err != nil { log.Errorf("Docker: problem with bridge %s: %v", *dockerBridge, err) } if registry, err := docker.NewRegistry(*dockerInterval, clients); err == nil { defer registry.Stop() p.AddTagger(docker.NewTagger(registry, processCache)) p.AddReporter(docker.NewReporter(registry, hostID, p)) } else { log.Errorf("Docker: failed to start registry: %v", err) } } if *kubernetesEnabled { if client, err := kubernetes.NewClient(*kubernetesAPI, *kubernetesInterval); err == nil { defer client.Stop() p.AddReporter(kubernetes.NewReporter(client)) } else { log.Errorf("Kubernetes: failed to start client: %v", err) log.Errorf("Kubernetes: make sure to run Scope inside a POD with a service account or provide a valid kubernetes.api url") } } if *weaveRouterAddr != "" { client := weave.NewClient(sanitize.URL("http://", 6784, "")(*weaveRouterAddr)) weave := overlay.NewWeave(hostID, client) defer weave.Stop() p.AddTagger(weave) p.AddReporter(weave) dockerBridgeIP, err := getFirstAddressOf(*dockerBridge) if err != nil { log.Println("Error getting docker bridge ip:", err) } else { weaveDNSLookup := appclient.LookupUsing(dockerBridgeIP + ":53") weaveResolver := appclient.NewResolver([]string{*weaveDNSTarget}, weaveDNSLookup, clients.Set) defer weaveResolver.Stop() } } if *httpListen != "" { go func() { log.Infof("Profiling data being exported to %s", *httpListen) log.Infof("go tool pprof http://%s/debug/pprof/{profile,heap,block}", *httpListen) log.Infof("Profiling endpoint %s terminated: %v", *httpListen, http.ListenAndServe(*httpListen, nil)) }() } p.Start() defer p.Stop() common.SignalHandlerLoop() }
// Main runs the probe func probeMain(flags probeFlags) { setLogLevel(flags.logLevel) setLogFormatter(flags.logPrefix) // Setup in memory metrics sink inm := metrics.NewInmemSink(time.Minute, 2*time.Minute) sig := metrics.DefaultInmemSignal(inm) defer sig.Stop() metrics.NewGlobal(metrics.DefaultConfig("scope-probe"), inm) defer log.Info("probe exiting") if flags.spyProcs && os.Getegid() != 0 { log.Warn("--probe.process=true, but that requires root to find everything") } rand.Seed(time.Now().UnixNano()) var ( probeID = strconv.FormatInt(rand.Int63(), 16) hostName = hostname.Get() hostID = hostName // TODO(pb): we should sanitize the hostname ) log.Infof("probe starting, version %s, ID %s", version, probeID) log.Infof("command line: %v", os.Args) checkpointFlags := map[string]string{} if flags.kubernetesEnabled { checkpointFlags["kubernetes_enabled"] = "true" } go check(checkpointFlags) var targets = []string{} if flags.token != "" { // service mode if len(flag.Args()) == 0 { targets = append(targets, defaultServiceHost) } } else if !flags.noApp { targets = append(targets, fmt.Sprintf("localhost:%d", xfer.AppPort)) } targets = append(targets, flag.Args()...) log.Infof("publishing to: %s", strings.Join(targets, ", ")) probeConfig := appclient.ProbeConfig{ Token: flags.token, ProbeVersion: version, ProbeID: probeID, Insecure: flags.insecure, } clients := appclient.NewMultiAppClient(func(hostname, endpoint string) (appclient.AppClient, error) { return appclient.NewAppClient( probeConfig, hostname, endpoint, xfer.ControlHandlerFunc(controls.HandleControlRequest), ) }) defer clients.Stop() dnsLookupFn := net.LookupIP if flags.resolver != "" { dnsLookupFn = appclient.LookupUsing(flags.resolver) } resolver := appclient.NewResolver(targets, dnsLookupFn, clients.Set) defer resolver.Stop() p := probe.New(flags.spyInterval, flags.publishInterval, clients) hostReporter := host.NewReporter(hostID, hostName, probeID, version, clients) defer hostReporter.Stop() p.AddReporter(hostReporter) p.AddTagger(probe.NewTopologyTagger(), host.NewTagger(hostID)) var processCache *process.CachingWalker var scanner procspy.ConnectionScanner if flags.procEnabled { processCache = process.NewCachingWalker(process.NewWalker(flags.procRoot)) scanner = procspy.NewConnectionScanner(processCache) p.AddTicker(processCache) p.AddReporter(process.NewReporter(processCache, hostID, process.GetDeltaTotalJiffies)) } endpointReporter := endpoint.NewReporter(hostID, hostName, flags.spyProcs, flags.useConntrack, flags.procEnabled, scanner) defer endpointReporter.Stop() p.AddReporter(endpointReporter) if flags.dockerEnabled { // Don't add the bridge in Kubernetes since container IPs are global and // shouldn't be scoped if !flags.kubernetesEnabled { if err := report.AddLocalBridge(flags.dockerBridge); err != nil { log.Errorf("Docker: problem with bridge %s: %v", flags.dockerBridge, err) } } if registry, err := docker.NewRegistry(flags.dockerInterval, clients, true, hostID); err == nil { defer registry.Stop() if flags.procEnabled { p.AddTagger(docker.NewTagger(registry, processCache)) } p.AddReporter(docker.NewReporter(registry, hostID, probeID, p)) } else { log.Errorf("Docker: failed to start registry: %v", err) } } if flags.kubernetesEnabled { if client, err := kubernetes.NewClient(flags.kubernetesAPI, flags.kubernetesInterval); err == nil { defer client.Stop() reporter := kubernetes.NewReporter(client, clients, probeID, hostID, p) defer reporter.Stop() p.AddReporter(reporter) p.AddTagger(reporter) } else { log.Errorf("Kubernetes: failed to start client: %v", err) log.Errorf("Kubernetes: make sure to run Scope inside a POD with a service account or provide a valid kubernetes.api url") } } if flags.weaveAddr != "" { client := weave.NewClient(sanitize.URL("http://", 6784, "")(flags.weaveAddr)) weave := overlay.NewWeave(hostID, client) defer weave.Stop() p.AddTagger(weave) p.AddReporter(weave) dockerBridgeIP, err := network.GetFirstAddressOf(flags.dockerBridge) if err != nil { log.Println("Error getting docker bridge ip:", err) } else { weaveDNSLookup := appclient.LookupUsing(dockerBridgeIP + ":53") weaveResolver := appclient.NewResolver([]string{flags.weaveHostname}, weaveDNSLookup, clients.Set) defer weaveResolver.Stop() } } pluginRegistry, err := plugins.NewRegistry( flags.pluginsRoot, pluginAPIVersion, map[string]string{ "probe_id": probeID, "api_version": pluginAPIVersion, }, ) if err != nil { log.Errorf("plugins: problem loading: %v", err) } else { defer pluginRegistry.Close() p.AddReporter(pluginRegistry) } if flags.httpListen != "" { go func() { log.Infof("Profiling data being exported to %s", flags.httpListen) log.Infof("go tool pprof http://%s/debug/pprof/{profile,heap,block}", flags.httpListen) log.Infof("Profiling endpoint %s terminated: %v", flags.httpListen, http.ListenAndServe(flags.httpListen, nil)) }() } p.Start() defer p.Stop() common.SignalHandlerLoop() }
func main() { procs := runtime.NumCPU() // packet sniffing can block an OS thread, so we need one thread // for that plus at least one more. if procs < 2 { procs = 2 } runtime.GOMAXPROCS(procs) var ( justVersion bool config mesh.Config networkConfig weave.NetworkConfig protocolMinVersion int resume bool ifaceName string routerName string nickName string password string pktdebug bool logLevel string prof string bufSzMB int noDiscovery bool httpAddr string ipamConfig ipamConfig dockerAPI string peers []string noDNS bool dnsConfig dnsConfig datapathName string trustedSubnetStr string dbPrefix string isAWSVPC bool defaultDockerHost = "unix:///var/run/docker.sock" ) if val := os.Getenv("DOCKER_HOST"); val != "" { defaultDockerHost = val } mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit") mflag.StringVar(&config.Host, []string{"-host"}, "", "router host") mflag.IntVar(&config.Port, []string{"#port", "-port"}, mesh.Port, "router port") mflag.IntVar(&protocolMinVersion, []string{"-min-protocol-version"}, mesh.ProtocolMinVersion, "minimum weave protocol version") mflag.BoolVar(&resume, []string{"-resume"}, false, "resume connections to previous peers") mflag.StringVar(&ifaceName, []string{"#iface", "-iface"}, "", "name of interface to capture/inject from (disabled if blank)") mflag.StringVar(&routerName, []string{"#name", "-name"}, "", "name of router (defaults to MAC of interface)") mflag.StringVar(&nickName, []string{"#nickname", "-nickname"}, "", "nickname of peer (defaults to hostname)") mflag.StringVar(&password, []string{"#password", "-password"}, "", "network password") mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)") mflag.BoolVar(&pktdebug, []string{"#pktdebug", "#-pktdebug", "-pkt-debug"}, false, "enable per-packet debug logging") mflag.StringVar(&prof, []string{"#profile", "-profile"}, "", "enable profiling and write profiles to given path") mflag.IntVar(&config.ConnLimit, []string{"#connlimit", "#-connlimit", "-conn-limit"}, 30, "connection limit (0 for unlimited)") mflag.BoolVar(&noDiscovery, []string{"#nodiscovery", "#-nodiscovery", "-no-discovery"}, false, "disable peer discovery") mflag.IntVar(&bufSzMB, []string{"#bufsz", "-bufsz"}, 8, "capture buffer size in MB") mflag.StringVar(&httpAddr, []string{"#httpaddr", "#-httpaddr", "-http-addr"}, "", "address to bind HTTP interface to (disabled if blank, absolute path indicates unix domain socket)") mflag.StringVar(&ipamConfig.Mode, []string{"-ipalloc-init"}, "", "allocator initialisation strategy (consensus, seed or observer)") mflag.StringVar(&ipamConfig.IPRangeCIDR, []string{"#iprange", "#-iprange", "-ipalloc-range"}, "", "IP address range reserved for automatic allocation, in CIDR notation") mflag.StringVar(&ipamConfig.IPSubnetCIDR, []string{"#ipsubnet", "#-ipsubnet", "-ipalloc-default-subnet"}, "", "subnet to allocate within by default, in CIDR notation") mflag.IntVar(&ipamConfig.PeerCount, []string{"#initpeercount", "#-initpeercount", "-init-peer-count"}, 0, "number of peers in network (for IP address allocation)") mflag.StringVar(&dockerAPI, []string{"#api", "#-api", "-docker-api"}, defaultDockerHost, "Docker API endpoint") mflag.BoolVar(&noDNS, []string{"-no-dns"}, false, "disable DNS server") mflag.StringVar(&dnsConfig.Domain, []string{"-dns-domain"}, nameserver.DefaultDomain, "local domain to server requests for") mflag.StringVar(&dnsConfig.ListenAddress, []string{"-dns-listen-address"}, nameserver.DefaultListenAddress, "address to listen on for DNS requests") mflag.IntVar(&dnsConfig.TTL, []string{"-dns-ttl"}, nameserver.DefaultTTL, "TTL for DNS request from our domain") mflag.DurationVar(&dnsConfig.ClientTimeout, []string{"-dns-fallback-timeout"}, nameserver.DefaultClientTimeout, "timeout for fallback DNS requests") mflag.StringVar(&dnsConfig.EffectiveListenAddress, []string{"-dns-effective-listen-address"}, "", "address DNS will actually be listening, after Docker port mapping") mflag.StringVar(&dnsConfig.ResolvConf, []string{"-resolv-conf"}, "", "path to resolver configuration for fallback DNS lookups") mflag.StringVar(&datapathName, []string{"-datapath"}, "", "ODP datapath name") mflag.StringVar(&trustedSubnetStr, []string{"-trusted-subnets"}, "", "comma-separated list of trusted subnets in CIDR notation") mflag.StringVar(&dbPrefix, []string{"-db-prefix"}, "/weavedb/weave", "pathname/prefix of filename to store data") mflag.BoolVar(&isAWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing") // crude way of detecting that we probably have been started in a // container, with `weave launch` --> suppress misleading paths in // mflags error messages. if os.Args[0] == "/home/weave/weaver" { // matches the Dockerfile ENTRYPOINT os.Args[0] = "weave" mflag.CommandLine.Init("weave", mflag.ExitOnError) } mflag.Parse() peers = mflag.Args() if resume && len(peers) > 0 { Log.Fatalf("You must not specify an initial peer list in conjunction with --resume") } common.SetLogLevel(logLevel) if justVersion { fmt.Printf("weave router %s\n", version) os.Exit(0) } Log.Println("Command line options:", options()) if prof != "" { defer profile.Start(profile.CPUProfile, profile.ProfilePath(prof), profile.NoShutdownHook).Stop() } if protocolMinVersion < mesh.ProtocolMinVersion || protocolMinVersion > mesh.ProtocolMaxVersion { Log.Fatalf("--min-protocol-version must be in range [%d,%d]", mesh.ProtocolMinVersion, mesh.ProtocolMaxVersion) } config.ProtocolMinVersion = byte(protocolMinVersion) if pktdebug { networkConfig.PacketLogging = packetLogging{} } else { networkConfig.PacketLogging = nopPacketLogging{} } overlay, bridge := createOverlay(datapathName, ifaceName, isAWSVPC, config.Host, config.Port, bufSzMB) networkConfig.Bridge = bridge name := peerName(routerName, bridge.Interface()) if nickName == "" { var err error nickName, err = os.Hostname() checkFatal(err) } config.Password = determinePassword(password) config.TrustedSubnets = parseTrustedSubnets(trustedSubnetStr) config.PeerDiscovery = !noDiscovery if isAWSVPC && len(config.Password) > 0 { Log.Fatalf("--awsvpc mode is not compatible with the --password option") } db, err := db.NewBoltDB(dbPrefix + "data.db") checkFatal(err) defer db.Close() router := weave.NewNetworkRouter(config, networkConfig, name, nickName, overlay, db) Log.Println("Our name is", router.Ourself) if peers, err = router.InitialPeers(resume, peers); err != nil { Log.Fatal("Unable to get initial peer set: ", err) } var dockerCli *docker.Client dockerVersion := "none" if dockerAPI != "" { dc, err := docker.NewClient(dockerAPI) if err != nil { Log.Fatal("Unable to start docker client: ", err) } else { Log.Info(dc.Info()) } dockerCli = dc dockerVersion = dockerCli.DockerVersion() } network := "" if isAWSVPC { network = "awsvpc" } checkForUpdates(dockerVersion, network) observeContainers := func(o docker.ContainerObserver) { if dockerCli != nil { if err := dockerCli.AddObserver(o); err != nil { Log.Fatal("Unable to start watcher", err) } } } isKnownPeer := func(name mesh.PeerName) bool { return router.Peers.Fetch(name) != nil } var ( allocator *ipam.Allocator defaultSubnet address.CIDR trackerName string ) if ipamConfig.Enabled() { var t tracker.LocalRangeTracker if isAWSVPC { Log.Infoln("Creating AWSVPC LocalRangeTracker") t, err = tracker.NewAWSVPCTracker() if err != nil { Log.Fatalf("Cannot create AWSVPC LocalRangeTracker: %s", err) } trackerName = "awsvpc" } allocator, defaultSubnet = createAllocator(router, ipamConfig, db, t, isKnownPeer) observeContainers(allocator) if dockerCli != nil { ids, err := dockerCli.AllContainerIDs() checkFatal(err) allocator.PruneOwned(ids) } } var ( ns *nameserver.Nameserver dnsserver *nameserver.DNSServer ) if !noDNS { ns, dnsserver = createDNSServer(dnsConfig, router.Router, isKnownPeer) observeContainers(ns) ns.Start() defer ns.Stop() dnsserver.ActivateAndServe() defer dnsserver.Stop() } router.Start() if errors := router.InitiateConnections(peers, false); len(errors) > 0 { Log.Fatal(common.ErrorMessages(errors)) } // The weave script always waits for a status call to succeed, // so there is no point in doing "weave launch --http-addr ''". // This is here to support stand-alone use of weaver. if httpAddr != "" { muxRouter := mux.NewRouter() if allocator != nil { allocator.HandleHTTP(muxRouter, defaultSubnet, trackerName, dockerCli) } if ns != nil { ns.HandleHTTP(muxRouter, dockerCli) } router.HandleHTTP(muxRouter) HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver) http.Handle("/", common.LoggingHTTPHandler(muxRouter)) Log.Println("Listening for HTTP control messages on", httpAddr) go listenAndServeHTTP(httpAddr) } common.SignalHandlerLoop(router) }
// Main runs the app func appMain(flags appFlags) { setLogLevel(flags.logLevel) setLogFormatter(flags.logPrefix) userIDer := multitenant.NoopUserIDer if flags.userIDHeader != "" { userIDer = multitenant.UserIDHeader(flags.userIDHeader) } collector, err := collectorFactory(userIDer, flags.collectorURL, flags.window, flags.awsCreateTables) if err != nil { log.Fatalf("Error creating collector: %v", err) return } controlRouter, err := controlRouterFactory(userIDer, flags.controlRouterURL) if err != nil { log.Fatalf("Error creating control router: %v", err) return } pipeRouter, err := pipeRouterFactory(userIDer, flags.pipeRouterURL, flags.consulInf) if err != nil { log.Fatalf("Error creating pipe router: %v", err) return } defer log.Info("app exiting") rand.Seed(time.Now().UnixNano()) app.UniqueID = strconv.FormatInt(rand.Int63(), 16) app.Version = version log.Infof("app starting, version %s, ID %s", app.Version, app.UniqueID) log.Infof("command line: %v", os.Args) // Start background version checking checkpoint.CheckInterval(&checkpoint.CheckParams{ Product: "scope-app", Version: app.Version, }, versionCheckPeriod, func(r *checkpoint.CheckResponse, err error) { if err != nil { log.Errorf("Error checking version: %v", err) } else if r.Outdated { log.Infof("Scope version %s is available; please update at %s", r.CurrentVersion, r.CurrentDownloadURL) app.NewVersion(r.CurrentVersion, r.CurrentDownloadURL) } }) // If user supplied a weave router address, periodically try and register // out IP address in WeaveDNS. if flags.weaveAddr != "" { weave, err := newWeavePublisher( flags.dockerEndpoint, flags.weaveAddr, flags.weaveHostname, flags.containerName) if err != nil { log.Println("Failed to start weave integration:", err) } else { defer weave.Stop() } } handler := router(collector, controlRouter, pipeRouter) if flags.logHTTP { handler = middleware.Logging.Wrap(handler) } go func() { log.Infof("listening on %s", flags.listen) log.Info(http.ListenAndServe(flags.listen, handler)) }() common.SignalHandlerLoop() }