diff --git a/etcd/etcd.go b/etcd/etcd.go index 13d85f79..71dfb530 100644 --- a/etcd/etcd.go +++ b/etcd/etcd.go @@ -176,12 +176,14 @@ type EmbdEtcd struct { // EMBeddeD etcd exitchan chan struct{} exitTimeout <-chan time.Time - hostname string - memberID uint64 // cluster membership id of server if running - endpoints etcdtypes.URLsMap // map of servers a client could connect to - clientURLs etcdtypes.URLs // locations to listen for clients if i am a server - serverURLs etcdtypes.URLs // locations to listen for servers if i am a server (peer) - noServer bool // disable all server peering if true + hostname string + memberID uint64 // cluster membership id of server if running + endpoints etcdtypes.URLsMap // map of servers a client could connect to + clientURLs etcdtypes.URLs // locations to listen for clients if i am a server + serverURLs etcdtypes.URLs // locations to listen for servers if i am a server (peer) + advertiseClientURLs etcdtypes.URLs // client urls to advertise + advertiseServerURLs etcdtypes.URLs // server urls to advertise + noServer bool // disable all server peering if true // local tracked state nominated etcdtypes.URLsMap // copy of who's nominated to locally track state @@ -208,7 +210,7 @@ type EmbdEtcd struct { // EMBeddeD etcd } // NewEmbdEtcd creates the top level embedded etcd struct client and server obj. -func NewEmbdEtcd(hostname string, seeds, clientURLs, serverURLs etcdtypes.URLs, noServer bool, idealClusterSize uint16, flags Flags, prefix string, converger converger.Converger) *EmbdEtcd { +func NewEmbdEtcd(hostname string, seeds, clientURLs, serverURLs, advertiseClientURLs, advertiseServerURLs etcdtypes.URLs, noServer bool, idealClusterSize uint16, flags Flags, prefix string, converger converger.Converger) *EmbdEtcd { endpoints := make(etcdtypes.URLsMap) if hostname == seedSentinel { // safety return nil @@ -229,11 +231,13 @@ func NewEmbdEtcd(hostname string, seeds, clientURLs, serverURLs etcdtypes.URLs, nominated: make(etcdtypes.URLsMap), - hostname: hostname, - endpoints: endpoints, - clientURLs: clientURLs, - serverURLs: serverURLs, - noServer: noServer, + hostname: hostname, + endpoints: endpoints, + clientURLs: clientURLs, + serverURLs: serverURLs, + advertiseClientURLs: advertiseClientURLs, + advertiseServerURLs: advertiseServerURLs, + noServer: noServer, idealClusterSize: idealClusterSize, converger: converger, @@ -1647,14 +1651,23 @@ func (obj *EmbdEtcd) StartServer(newCluster bool, peerURLsMap etcdtypes.URLsMap) initialPeerURLsMap[memberName] = peerURLs } + aCUrls := obj.clientURLs + if len(obj.advertiseClientURLs) > 0 { + aCUrls = obj.advertiseClientURLs + } + aPUrls := peerURLs + if len(obj.advertiseServerURLs) > 0 { + aPUrls = obj.advertiseServerURLs + } + // embed etcd cfg := embed.NewConfig() cfg.Name = memberName // hostname cfg.Dir = obj.dataDir - cfg.ACUrls = obj.clientURLs - cfg.APUrls = peerURLs cfg.LCUrls = obj.clientURLs cfg.LPUrls = peerURLs + cfg.ACUrls = aCUrls + cfg.APUrls = aPUrls cfg.StrictReconfigCheck = false // XXX: workaround https://github.com/coreos/etcd/issues/6305 cfg.InitialCluster = initialPeerURLsMap.String() // including myself! diff --git a/lib/cli.go b/lib/cli.go index 8c8d54aa..5f4d53e4 100644 --- a/lib/cli.go +++ b/lib/cli.go @@ -114,6 +114,8 @@ func run(c *cli.Context) error { obj.Seeds = c.StringSlice("seeds") obj.ClientURLs = c.StringSlice("client-urls") obj.ServerURLs = c.StringSlice("server-urls") + obj.AdvertiseClientURLs = c.StringSlice("advertise-client-urls") + obj.AdvertiseServerURLs = c.StringSlice("advertise-server-urls") obj.IdealClusterSize = c.Int("ideal-cluster-size") obj.NoServer = c.Bool("no-server") @@ -318,6 +320,20 @@ func CLI(program, version string, flags Flags) error { Usage: "list of URLs to listen on for server (peer) traffic", EnvVar: "MGMT_SERVER_URLS", }, + // port 2379 and 4001 are common + cli.StringSliceFlag{ + Name: "advertise-client-urls", + Value: &cli.StringSlice{}, + Usage: "list of URLs to listen on for client traffic", + EnvVar: "MGMT_ADVERTISE_CLIENT_URLS", + }, + // port 2380 and 7001 are common + cli.StringSliceFlag{ + Name: "advertise-server-urls, advertise-peer-urls", + Value: &cli.StringSlice{}, + Usage: "list of URLs to listen on for server (peer) traffic", + EnvVar: "MGMT_ADVERTISE_SERVER_URLS", + }, cli.IntFlag{ Name: "ideal-cluster-size", Value: -1, diff --git a/lib/main.go b/lib/main.go index 1c412186..8a9f7124 100644 --- a/lib/main.go +++ b/lib/main.go @@ -76,11 +76,13 @@ type Main struct { ConvergedTimeout int // exit after approximately this many seconds in a converged state; -1 to disable MaxRuntime uint // exit after a maximum of approximately this many seconds - Seeds []string // default etc client endpoint - ClientURLs []string // list of URLs to listen on for client traffic - ServerURLs []string // list of URLs to listen on for server (peer) traffic - IdealClusterSize int // ideal number of server peers in cluster; only read by initial server - NoServer bool // do not let other servers peer with me + Seeds []string // default etc client endpoint + ClientURLs []string // list of URLs to listen on for client traffic + ServerURLs []string // list of URLs to listen on for server (peer) traffic + AdvertiseClientURLs []string // list of URLs to advertise for client traffic + AdvertiseServerURLs []string // list of URLs to advertise for server (peer) traffic + IdealClusterSize int // ideal number of server peers in cluster; only read by initial server + NoServer bool // do not let other servers peer with me CConns uint16 // number of maximum concurrent remote ssh connections to run, 0 for unlimited AllowInteractive bool // allow interactive prompting, such as for remote passwords @@ -88,10 +90,12 @@ type Main struct { NoCaching bool // don't allow remote caching of remote execution binary Depth uint16 // depth in remote hierarchy; for internal use only - seeds etcdtypes.URLs // processed seeds value - clientURLs etcdtypes.URLs // processed client urls value - serverURLs etcdtypes.URLs // processed server urls value - idealClusterSize uint16 // processed ideal cluster size value + seeds etcdtypes.URLs // processed seeds value + clientURLs etcdtypes.URLs // processed client urls value + serverURLs etcdtypes.URLs // processed server urls value + advertiseClientURLs etcdtypes.URLs // processed advertise client urls value + advertiseServerURLs etcdtypes.URLs // processed advertise server urls value + idealClusterSize uint16 // processed ideal cluster size value NoPgp bool // disallow pgp functionality PgpKeyPath *string // import a pre-made key pair @@ -173,6 +177,18 @@ func (obj *Main) Init() error { if err != nil && len(obj.ServerURLs) > 0 { return fmt.Errorf("the ServerURLs didn't parse correctly") } + obj.advertiseClientURLs, err = etcdtypes.NewURLs( + util.FlattenListWithSplit(obj.AdvertiseClientURLs, []string{",", ";", " "}), + ) + if err != nil && len(obj.AdvertiseClientURLs) > 0 { + return fmt.Errorf("the AdvertiseClientURLs didn't parse correctly") + } + obj.advertiseServerURLs, err = etcdtypes.NewURLs( + util.FlattenListWithSplit(obj.AdvertiseServerURLs, []string{",", ";", " "}), + ) + if err != nil && len(obj.AdvertiseServerURLs) > 0 { + return fmt.Errorf("the AdvertiseServerURLs didn't parse correctly") + } obj.exit = make(chan error) return nil @@ -330,6 +346,8 @@ func (obj *Main) Run() error { obj.seeds, obj.clientURLs, obj.serverURLs, + obj.advertiseClientURLs, + obj.advertiseServerURLs, obj.NoServer, obj.idealClusterSize, etcd.Flags{