func getFleetRegistryClient(fleetEndpoints []string) (fleetClient.API, error) { var dial func(string, string) (net.Conn, error) tlsConfig, err := fleetPkg.ReadTLSConfigFiles("", "", "") if err != nil { return nil, err } trans := &http.Transport{ Dial: dial, TLSClientConfig: tlsConfig, } timeout := 3 * time.Second eCfg := etcd.Config{ Endpoints: fleetEndpoints, Transport: trans, } eClient, err := etcd.New(eCfg) if err != nil { return nil, err } kAPI := etcd.NewKeysAPI(eClient) reg := registry.NewEtcdRegistry(kAPI, registry.DefaultKeyPrefix, timeout) return &fleetClient.RegistryClient{Registry: reg}, nil }
func getFleetRegistryClient() (fleetClient.API, error) { var dial func(string, string) (net.Conn, error) tlsConfig, err := fleetPkg.ReadTLSConfigFiles("", "", "") if err != nil { return nil, err } trans := &http.Transport{ Dial: dial, TLSClientConfig: tlsConfig, } timeout := 3 * 1000 * time.Millisecond machines := strings.Split(*argEndpoints, ",") eClient, err := etcd.NewClient(machines, trans, timeout) if err != nil { return nil, err } reg := registry.NewEtcdRegistry(eClient, "/_coreos.com/fleet/") return &fleetClient.RegistryClient{Registry: reg}, nil }
func getRegistryClient(cCmd *cobra.Command) (client.API, error) { var dial func(string, string) (net.Conn, error) SSHUserName, _ := cmdFleet.PersistentFlags().GetString("ssh-username") tun := getTunnelFlag(cCmd) if tun != "" { sshClient, err := ssh.NewSSHClient(SSHUserName, tun, getChecker(cCmd), false, getSSHTimeoutFlag(cCmd)) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } dial = func(network, addr string) (net.Conn, error) { tcpaddr, err := net.ResolveTCPAddr(network, addr) if err != nil { return nil, err } return sshClient.DialTCP(network, nil, tcpaddr) } } CAFile, _ := cmdFleet.PersistentFlags().GetString("ca-file") CertFile, _ := cmdFleet.PersistentFlags().GetString("cert-file") KeyFile, _ := cmdFleet.PersistentFlags().GetString("key-file") tlsConfig, err := pkg.ReadTLSConfigFiles(CAFile, CertFile, KeyFile) if err != nil { return nil, err } trans := &http.Transport{ Dial: dial, TLSClientConfig: tlsConfig, } endPoint, _ := cmdFleet.PersistentFlags().GetString("endpoint") eCfg := etcd.Config{ Endpoints: strings.Split(endPoint, ","), Transport: trans, HeaderTimeoutPerRequest: getRequestTimeoutFlag(cCmd), } eClient, err := etcd.New(eCfg) if err != nil { return nil, err } etcdKeyPrefix, _ := cmdFleet.PersistentFlags().GetString("etcd-key-prefix") kAPI := etcd.NewKeysAPI(eClient) reg := registry.NewEtcdRegistry(kAPI, etcdKeyPrefix) if msg, ok := checkVersion(reg); !ok { stderr(msg) } return &client.RegistryClient{Registry: reg}, nil }
func getRegistryClient(config FleetConfig) (client.API, error) { var dial func(string, string) (net.Conn, error) tun := config.Tunnel if tun != "" { sshClient, err := ssh.NewSSHClient(config.SSHUserName, tun, getChecker(config), false, config.SSHTimeout) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } dial = func(network, addr string) (net.Conn, error) { tcpaddr, err := net.ResolveTCPAddr(network, addr) if err != nil { return nil, err } return sshClient.DialTCP(network, nil, tcpaddr) } } tlsConfig, err := pkg.ReadTLSConfigFiles(config.CAFile, config.CertFile, config.KeyFile) if err != nil { return nil, err } trans := &http.Transport{ Dial: dial, TLSClientConfig: tlsConfig, } eCfg := etcd.Config{ Endpoints: strings.Split(config.EndPoint, ","), Transport: trans, HeaderTimeoutPerRequest: config.RequestTimeout, } eClient, err := etcd.New(eCfg) if err != nil { return nil, err } kAPI := etcd.NewKeysAPI(eClient) reg := registry.NewEtcdRegistry(kAPI, config.EtcdKeyPrefix) /*if msg, ok := checkVersion(reg); !ok { stderr(msg) }*/ return &client.RegistryClient{Registry: reg}, nil }
func getRegistryClient() (client.API, error) { var dial func(string, string) (net.Conn, error) sshTimeout := time.Duration(Flags.SSHTimeout*1000) * time.Millisecond tun := getTunnelFlag() if tun != "" { sshClient, err := ssh.NewSSHClient("core", tun, getChecker(), false, sshTimeout) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } dial = func(network, addr string) (net.Conn, error) { tcpaddr, err := net.ResolveTCPAddr(network, addr) if err != nil { return nil, err } return sshClient.DialTCP(network, nil, tcpaddr) } } tlsConfig, err := pkg.ReadTLSConfigFiles(Flags.EtcdCAFile, Flags.EtcdCertFile, Flags.EtcdKeyFile) if err != nil { return nil, err } trans := &http.Transport{ Dial: dial, TLSClientConfig: tlsConfig, } timeout := time.Duration(Flags.RequestTimeout*1000) * time.Millisecond machines := []string{Flags.Endpoint} eClient, err := etcd.NewClient(machines, trans, timeout) if err != nil { return nil, err } reg := registry.NewEtcdRegistry(eClient, Flags.EtcdKeyPrefix) // if msg, ok := checkVersion(reg); !ok { // stderr(msg) // } return &client.RegistryClient{Registry: reg}, nil }
func getEtcdClient() (*etcdClient, error) { var dial func(string, string) (net.Conn, error) sshTimeout := time.Duration(fleet.Flags.SSHTimeout*1000) * time.Millisecond tun := getTunnelFlag() if tun != "" { sshClient, err := ssh.NewSSHClient("core", tun, getChecker(), false, sshTimeout) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } dial = func(network, addr string) (net.Conn, error) { tcpaddr, err := net.ResolveTCPAddr(network, addr) if err != nil { return nil, err } return sshClient.DialTCP(network, nil, tcpaddr) } } tlsConfig, err := pkg.ReadTLSConfigFiles(fleet.Flags.EtcdCAFile, fleet.Flags.EtcdCertFile, fleet.Flags.EtcdKeyFile) if err != nil { return nil, err } trans := http.Transport{ Dial: dial, TLSClientConfig: tlsConfig, } timeout := time.Duration(fleet.Flags.RequestTimeout*1000) * time.Millisecond machines := []string{fleet.Flags.Endpoint} c := etcd.NewClient(machines) c.SetDialTimeout(timeout) // use custom transport with SSH tunnel capability c.SetTransport(&trans) return &etcdClient{etcd: c}, nil }
func getFleetRegistryClient(fleetEndpoints []string) (fleetClient.API, error) { var dial func(string, string) (net.Conn, error) tlsConfig, err := fleetPkg.ReadTLSConfigFiles("", "", "") if err != nil { return nil, err } trans := &http.Transport{ Dial: dial, TLSClientConfig: tlsConfig, } timeout := 3 * time.Second eClient, err := etcd.NewClient(fleetEndpoints, trans, timeout) if err != nil { return nil, err } reg := registry.NewEtcdRegistry(eClient, etcdRegistry) return &fleetClient.RegistryClient{Registry: reg}, nil }
func getHTTPClient() (client.API, error) { endpoints := strings.Split(globalFlags.Endpoint, ",") if len(endpoints) > 1 { log.Warningf("multiple endpoints provided but only the first (%s) is used", endpoints[0]) } ep, err := url.Parse(endpoints[0]) if err != nil { return nil, err } if len(ep.Scheme) == 0 { return nil, errors.New("URL scheme undefined") } tun := getTunnelFlag() tunneling := tun != "" dialUnix := ep.Scheme == "unix" || ep.Scheme == "file" tunnelFunc := net.Dial if tunneling { sshClient, err := ssh.NewSSHClient(globalFlags.SSHUserName, tun, getChecker(), true, getSSHTimeoutFlag()) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } if dialUnix { tgt := ep.Path tunnelFunc = func(string, string) (net.Conn, error) { log.Debugf("Establishing remote fleetctl proxy to %s", tgt) cmd := fmt.Sprintf(`fleetctl fd-forward %s`, tgt) return ssh.DialCommand(sshClient, cmd) } } else { tunnelFunc = sshClient.Dial } } dialFunc := tunnelFunc if dialUnix { // This commonly happens if the user misses the leading slash after the scheme. // For example, "unix://var/run/fleet.sock" would be parsed as host "var". if len(ep.Host) > 0 { return nil, fmt.Errorf("unable to connect to host %q with scheme %q", ep.Host, ep.Scheme) } // The Path field is only used for dialing and should not be used when // building any further HTTP requests. sockPath := ep.Path ep.Path = "" // If not tunneling to the unix socket, http.Client will dial it directly. // http.Client does not natively support dialing a unix domain socket, so the // dial function must be overridden. if !tunneling { dialFunc = func(string, string) (net.Conn, error) { return net.Dial("unix", sockPath) } } // http.Client doesn't support the schemes "unix" or "file", but it // is safe to use "http" as dialFunc ignores it anyway. ep.Scheme = "http" // The Host field is not used for dialing, but will be exposed in debug logs. ep.Host = "domain-sock" } tlsConfig, err := pkg.ReadTLSConfigFiles(globalFlags.CAFile, globalFlags.CertFile, globalFlags.KeyFile) if err != nil { return nil, err } trans := pkg.LoggingHTTPTransport{ Transport: http.Transport{ Dial: dialFunc, TLSClientConfig: tlsConfig, }, } hc := http.Client{ Transport: &trans, } return client.NewHTTPClient(&hc, *ep) }
func New(cfg config.Config) (*Server, error) { agentTTL, err := time.ParseDuration(cfg.AgentTTL) if err != nil { return nil, err } mgr, err := systemd.NewSystemdUnitManager(systemd.DefaultUnitsDirectory) if err != nil { return nil, err } mach, err := newMachineFromConfig(cfg, mgr) if err != nil { return nil, err } tlsConfig, err := pkg.ReadTLSConfigFiles(cfg.EtcdCAFile, cfg.EtcdCertFile, cfg.EtcdKeyFile) if err != nil { return nil, err } eCfg := etcd.Config{ Transport: &http.Transport{TLSClientConfig: tlsConfig}, Endpoints: cfg.EtcdServers, } eClient, err := etcd.New(eCfg) if err != nil { return nil, err } etcdRequestTimeout := time.Duration(cfg.EtcdRequestTimeout*1000) * time.Millisecond kAPI := etcd.NewKeysAPI(eClient) reg := registry.NewEtcdRegistry(kAPI, cfg.EtcdKeyPrefix, etcdRequestTimeout) pub := agent.NewUnitStatePublisher(reg, mach, agentTTL) gen := unit.NewUnitStateGenerator(mgr) a := agent.New(mgr, gen, reg, mach, agentTTL) var rStream pkg.EventStream if !cfg.DisableWatches { rStream = registry.NewEtcdEventStream(kAPI, cfg.EtcdKeyPrefix) } lManager := lease.NewEtcdLeaseManager(kAPI, cfg.EtcdKeyPrefix, etcdRequestTimeout) ar := agent.NewReconciler(reg, rStream) e := engine.New(reg, lManager, rStream, mach) listeners, err := activation.Listeners(false) if err != nil { return nil, err } hrt := heart.New(reg, mach) mon := heart.NewMonitor(agentTTL) apiServer := api.NewServer(listeners, api.NewServeMux(reg, cfg.TokenLimit)) apiServer.Serve() eIval := time.Duration(cfg.EngineReconcileInterval*1000) * time.Millisecond srv := Server{ agent: a, aReconciler: ar, usGen: gen, usPub: pub, engine: e, mach: mach, hrt: hrt, mon: mon, api: apiServer, stop: nil, engineReconcileInterval: eIval, disableEngine: cfg.DisableEngine, } return &srv, nil }
func New(cfg config.Config, listeners []net.Listener) (*Server, error) { agentTTL, err := time.ParseDuration(cfg.AgentTTL) if err != nil { return nil, err } mgr, err := systemd.NewSystemdUnitManager(cfg.UnitsDirectory, cfg.SystemdUser) if err != nil { return nil, err } mach, err := newMachineFromConfig(cfg, mgr) if err != nil { return nil, err } tlsConfig, err := pkg.ReadTLSConfigFiles(cfg.EtcdCAFile, cfg.EtcdCertFile, cfg.EtcdKeyFile) if err != nil { return nil, err } eCfg := etcd.Config{ Transport: &http.Transport{TLSClientConfig: tlsConfig}, Endpoints: cfg.EtcdServers, HeaderTimeoutPerRequest: (time.Duration(cfg.EtcdRequestTimeout*1000) * time.Millisecond), Username: cfg.EtcdUsername, Password: cfg.EtcdPassword, } eClient, err := etcd.New(eCfg) if err != nil { return nil, err } kAPI := etcd.NewKeysAPI(eClient) var ( reg engine.CompleteRegistry genericReg interface{} ) lManager := lease.NewEtcdLeaseManager(kAPI, cfg.EtcdKeyPrefix) if !cfg.EnableGRPC { genericReg = registry.NewEtcdRegistry(kAPI, cfg.EtcdKeyPrefix) if obj, ok := genericReg.(engine.CompleteRegistry); ok { reg = obj } } else { etcdReg := registry.NewEtcdRegistry(kAPI, cfg.EtcdKeyPrefix) genericReg = rpc.NewRegistryMux(etcdReg, mach, lManager) if obj, ok := genericReg.(engine.CompleteRegistry); ok { reg = obj } } pub := agent.NewUnitStatePublisher(reg, mach, agentTTL) gen := unit.NewUnitStateGenerator(mgr) a := agent.New(mgr, gen, reg, mach, agentTTL) var rStream pkg.EventStream if !cfg.DisableWatches { rStream = registry.NewEtcdEventStream(kAPI, cfg.EtcdKeyPrefix) } ar := agent.NewReconciler(reg, rStream) var e *engine.Engine if !cfg.EnableGRPC { e = engine.New(reg, lManager, rStream, mach, nil) } else { regMux := genericReg.(*rpc.RegistryMux) e = engine.New(reg, lManager, rStream, mach, regMux.EngineChanged) if cfg.DisableEngine { go regMux.ConnectToRegistry(e) } } if len(listeners) == 0 { listeners, err = activation.Listeners(false) if err != nil { return nil, err } } hrt := heart.New(reg, mach) mon := NewMonitor(agentTTL) apiServer := api.NewServer(listeners, api.NewServeMux(reg, cfg.TokenLimit)) apiServer.Serve() eIval := time.Duration(cfg.EngineReconcileInterval*1000) * time.Millisecond srv := Server{ agent: a, aReconciler: ar, usGen: gen, usPub: pub, engine: e, mach: mach, hrt: hrt, mon: mon, api: apiServer, killc: make(chan struct{}), stopc: nil, engineReconcileInterval: eIval, disableEngine: cfg.DisableEngine, reconfigServer: false, restartServer: false, } return &srv, nil }
func New(cfg config.Config) (*Server, error) { agentTTL, err := time.ParseDuration(cfg.AgentTTL) if err != nil { return nil, err } mgr, err := systemd.NewSystemdUnitManager(systemd.DefaultUnitsDirectory) if err != nil { return nil, err } mach, err := newMachineFromConfig(cfg, mgr) if err != nil { return nil, err } tlsConfig, err := pkg.ReadTLSConfigFiles(cfg.EtcdCAFile, cfg.EtcdCertFile, cfg.EtcdKeyFile) if err != nil { return nil, err } etcdRequestTimeout := time.Duration(cfg.EtcdRequestTimeout*1000) * time.Millisecond // set a per server request timeout that is the global request timeout divided by the number of quorum nodes (i.e. 3 out of 5) // this ensures that the the retry logic in etcd can try at least 3 servers before the global timeout fires and cancels the entire request quorumCount := (len(cfg.EtcdServers) / 2) + 1 etcdRequestPerServerTimeout := etcdRequestTimeout if quorumCount > 1 { etcdRequestPerServerTimeout = time.Duration(int64(etcdRequestTimeout) / int64(quorumCount)) } log.Infof("Etcd endpoints: %v", strings.Join(cfg.EtcdServers, ",")) log.Infof("Setting global request timeout of %v and per server request timeout of %v using a quorum count of %v", etcdRequestTimeout, etcdRequestPerServerTimeout, quorumCount) eCfg := etcd.Config{ Transport: &http.Transport{TLSClientConfig: tlsConfig}, Endpoints: cfg.EtcdServers, HeaderTimeoutPerRequest: etcdRequestPerServerTimeout, } eClient, err := etcd.New(eCfg) if err != nil { return nil, err } kAPI := etcd.NewKeysAPI(eClient) reg := registry.NewEtcdRegistry(kAPI, cfg.EtcdKeyPrefix, etcdRequestTimeout) pub := agent.NewUnitStatePublisher(reg, mach, agentTTL) gen := unit.NewUnitStateGenerator(mgr) a := agent.New(mgr, gen, reg, mach, agentTTL) rStream := registry.NewEtcdEventStream(kAPI, cfg.EtcdKeyPrefix) lManager := lease.NewEtcdLeaseManager(kAPI, cfg.EtcdKeyPrefix, etcdRequestTimeout) ar := agent.NewReconciler(reg, rStream) e := engine.New(reg, lManager, rStream, mach) listeners, err := activation.Listeners(false) if err != nil { return nil, err } hrt := heart.New(reg, mach) mon := heart.NewMonitor(agentTTL) apiServer := api.NewServer(listeners, api.NewServeMux(reg)) apiServer.Serve() eIval := time.Duration(cfg.EngineReconcileInterval*1000) * time.Millisecond srv := Server{ agent: a, aReconciler: ar, usGen: gen, usPub: pub, engine: e, mach: mach, hrt: hrt, mon: mon, api: apiServer, stop: nil, engineReconcileInterval: eIval, } return &srv, nil }
func New(cfg config.Config) (*Server, error) { etcdRequestTimeout := time.Duration(cfg.EtcdRequestTimeout*1000) * time.Millisecond agentTTL, err := time.ParseDuration(cfg.AgentTTL) if err != nil { return nil, err } mgr, err := systemd.NewSystemdUnitManager(systemd.DefaultUnitsDirectory) if err != nil { return nil, err } mach, err := newMachineFromConfig(cfg, mgr) if err != nil { return nil, err } tlsConfig, err := pkg.ReadTLSConfigFiles(cfg.EtcdCAFile, cfg.EtcdCertFile, cfg.EtcdKeyFile) if err != nil { return nil, err } eTrans := &http.Transport{TLSClientConfig: tlsConfig} eClient, err := etcd.NewClient(cfg.EtcdServers, eTrans, etcdRequestTimeout) if err != nil { return nil, err } reg := registry.NewEtcdRegistry(eClient, cfg.EtcdKeyPrefix) pub := agent.NewUnitStatePublisher(reg, mach, agentTTL) gen := unit.NewUnitStateGenerator(mgr) a := agent.New(mgr, gen, reg, mach, agentTTL) rStream := registry.NewEtcdEventStream(eClient, cfg.EtcdKeyPrefix) ar := agent.NewReconciler(reg, rStream) e := engine.New(reg, rStream, mach) listeners, err := activation.Listeners(false) if err != nil { return nil, err } hrt := heart.New(reg, mach) mon := heart.NewMonitor(agentTTL) apiServer := api.NewServer(listeners, api.NewServeMux(reg)) apiServer.Serve() eIval := time.Duration(cfg.EngineReconcileInterval*1000) * time.Millisecond srv := Server{ agent: a, aReconciler: ar, usGen: gen, usPub: pub, engine: e, mach: mach, hrt: hrt, mon: mon, api: apiServer, stop: nil, engineReconcileInterval: eIval, } return &srv, nil }
func getHTTPClient() (client.API, error) { ep, err := url.Parse(globalFlags.Endpoint) if err != nil { return nil, err } if len(ep.Scheme) == 0 { return nil, errors.New("URL scheme undefined") } tunnelFunc := net.Dial var tunneling bool tun := getTunnelFlag() if tun != "" { tunneling = true sshClient, err := ssh.NewSSHClient("core", tun, getChecker(), false, getSSHTimeoutFlag()) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } tunnelFunc = func(net, addr string) (net.Conn, error) { return sshClient.Dial(net, addr) } } dialFunc := tunnelFunc if ep.Scheme == "unix" || ep.Scheme == "file" { if tunneling { return nil, errors.New("unable to dial unix socket through SSH tunnel") } // This commonly happens if the user misses the leading slash after the scheme. // For example, "unix://var/run/fleet.sock" would be parsed as host "var". if len(ep.Host) > 0 { return nil, fmt.Errorf("unable to connect to host %q with scheme %q", ep.Host, ep.Scheme) } // The Path field is only used for dialing and should not be used when // building any further HTTP requests. sockPath := ep.Path ep.Path = "" // http.Client does not natively support dialing a unix domain socket, so the // dial function must be overridden. dialFunc = func(net, addr string) (net.Conn, error) { return tunnelFunc("unix", sockPath) } // http.Client doesn't support the schemes "unix" or "file", but it // is safe to use "http" as dialFunc ignores it anyway. ep.Scheme = "http" // The Host field is not used for dialing, but will be exposed in debug logs. ep.Host = "domain-sock" } tlsConfig, err := pkg.ReadTLSConfigFiles(globalFlags.CAFile, globalFlags.CertFile, globalFlags.KeyFile) if err != nil { return nil, err } trans := pkg.LoggingHTTPTransport{ Transport: http.Transport{ Dial: dialFunc, TLSClientConfig: tlsConfig, }, } hc := http.Client{ Transport: &trans, } return client.NewHTTPClient(&hc, *ep) }