add dynamic port for conf ports to local

This commit is contained in:
Felipe Madero
2022-09-23 18:34:09 -03:00
parent 91f7e03221
commit d46a2a39c3
8 changed files with 60 additions and 21 deletions
+1
View File
@@ -768,6 +768,7 @@ The helper function `NewDefaultNetwork` returns a network using a pre-defined co
func NewDefaultNetwork(
log logging.Logger,
binaryPath string,
reassignPortsIfUsed,
) (network.Network, error)
```
+1 -1
View File
@@ -68,7 +68,7 @@ func main() {
func run(log logging.Logger, binaryPath string) error {
// Create the network
nw, err := local.NewDefaultNetwork(log, binaryPath)
nw, err := local.NewDefaultNetwork(log, binaryPath, true)
if err != nil {
return err
}
+1 -1
View File
@@ -73,7 +73,7 @@ func main() {
func run(log logging.Logger, binaryPath string) error {
// Create the network
nw, err := local.NewDefaultNetwork(log, binaryPath)
nw, err := local.NewDefaultNetwork(log, binaryPath, true)
if err != nil {
return err
}
+8
View File
@@ -99,10 +99,12 @@ func getConfigEntry(
}
// getPort looks up the port config in the config file, if there is none, it tries to get a random free port from the OS
// if [reassingIfUsed] is true, and the port from config is not free, also tries to get a random free port
func getPort(
flags map[string]interface{},
configFile map[string]interface{},
portKey string,
reassignIfUsed bool,
) (port uint16, err error) {
if portIntf, ok := flags[portKey]; ok {
if portFromFlags, ok := portIntf.(int); ok {
@@ -126,6 +128,12 @@ func getPort(
return 0, fmt.Errorf("couldn't get free API port: %w", err)
}
}
if reassignIfUsed && !isFreePort(port) {
port, err = getFreePort()
if err != nil {
return 0, fmt.Errorf("couldn't get free API port: %w", err)
}
}
return port, nil
}
+28 -12
View File
@@ -100,6 +100,8 @@ type localNetwork struct {
chainConfigFiles map[string]string
// upgrade config files to use per default
upgradeConfigFiles map[string]string
// if true, for ports given in conf that are already taken, assign new random ones
reassignPortsIfUsed bool
}
var (
@@ -228,6 +230,7 @@ func NewNetwork(
networkConfig network.Config,
rootDir string,
snapshotsDir string,
reassignPortsIfUsed bool,
) (network.Network, error) {
net, err := newNetwork(
log,
@@ -240,6 +243,7 @@ func NewNetwork(
},
rootDir,
snapshotsDir,
reassignPortsIfUsed,
)
if err != nil {
return net, err
@@ -256,6 +260,7 @@ func newNetwork(
nodeProcessCreator NodeProcessCreator,
rootDir string,
snapshotsDir string,
reassignPortsIfUsed bool,
) (*localNetwork, error) {
var err error
if rootDir == "" {
@@ -275,15 +280,16 @@ func newNetwork(
}
// Create the network
net := &localNetwork{
nextNodeSuffix: 1,
nodes: map[string]*localNode{},
onStopCh: make(chan struct{}),
log: log,
bootstraps: beacon.NewSet(),
newAPIClientF: newAPIClientF,
nodeProcessCreator: nodeProcessCreator,
rootDir: rootDir,
snapshotsDir: snapshotsDir,
nextNodeSuffix: 1,
nodes: map[string]*localNode{},
onStopCh: make(chan struct{}),
log: log,
bootstraps: beacon.NewSet(),
newAPIClientF: newAPIClientF,
nodeProcessCreator: nodeProcessCreator,
rootDir: rootDir,
snapshotsDir: snapshotsDir,
reassignPortsIfUsed: reassignPortsIfUsed,
}
return net, nil
}
@@ -310,9 +316,10 @@ func newNetwork(
func NewDefaultNetwork(
log logging.Logger,
binaryPath string,
reassignPortsIfUsed bool,
) (network.Network, error) {
config := NewDefaultConfig(binaryPath)
return NewNetwork(log, config, "", "")
return NewNetwork(log, config, "", "", reassignPortsIfUsed)
}
func copyMapStringInterface(flags map[string]interface{}) map[string]interface{} {
@@ -858,14 +865,14 @@ func (ln *localNetwork) buildFlags(
}
// Use random free API port unless given in config file
apiPort, err := getPort(nodeConfig.Flags, configFile, config.HTTPPortKey)
apiPort, err := getPort(nodeConfig.Flags, configFile, config.HTTPPortKey, ln.reassignPortsIfUsed)
if err != nil {
return buildFlagsReturn{}, err
}
// Use a random free P2P (staking) port unless given in config file
// Use random free API port unless given in config file
p2pPort, err := getPort(nodeConfig.Flags, configFile, config.StakingPortKey)
p2pPort, err := getPort(nodeConfig.Flags, configFile, config.StakingPortKey, ln.reassignPortsIfUsed)
if err != nil {
return buildFlagsReturn{}, err
}
@@ -888,12 +895,21 @@ func (ln *localNetwork) buildFlags(
}
flags = append(flags, fileFlags...)
// avoid given these again, as apiPort/p2pPort can be dynamic even if given in nodeConfig
portFlags := map[string]struct{}{
config.HTTPPortKey: struct{}{},
config.StakingPortKey: struct{}{},
}
// Add flags given in node config.
// Note these will overwrite existing flags if the same flag is given twice.
for flagName, flagVal := range nodeConfig.Flags {
if _, ok := warnFlags[flagName]; ok {
ln.log.Warn("A provided flag can create conflicts with the runner. The suggestion is to remove this flag", zap.String("flag-name", flagName))
}
if _, ok := portFlags[flagName]; ok {
continue
}
flags = append(flags, fmt.Sprintf("--%s=%v", flagName, flagVal))
}
+2
View File
@@ -30,6 +30,7 @@ func NewNetworkFromSnapshot(
chainConfigs map[string]string,
upgradeConfigs map[string]string,
flags map[string]interface{},
reassignPortsIfUsed bool,
) (network.Network, error) {
net, err := newNetwork(
log,
@@ -42,6 +43,7 @@ func NewNetworkFromSnapshot(
},
rootDir,
snapshotsDir,
reassignPortsIfUsed,
)
if err != nil {
return net, err
+15 -6
View File
@@ -19,6 +19,19 @@ const (
netListenTimeout = 3 * time.Second
)
// isFreePort verifies a given [port] is free
func isFreePort(port uint16) bool {
// Verify it's free by binding to it
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
// Could not bind to [port]. Assumed to be not free.
return false
}
// We could bind to [port] so must be free.
_ = l.Close()
return true
}
// getFreePort generates a random port number and then
// verifies it is free. If it is, returns that port, otherwise retries.
// Returns an error if no free port is found within [netListenTimeout].
@@ -33,14 +46,10 @@ func getFreePort() (uint16, error) {
default:
// Generate random port in [minPort, maxPort]
port := uint16(rand.Intn(maxPort-minPort+1) + minPort)
// Verify it's free by binding to it
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
// Couldn't bind to this port. Try another.
if !isFreePort(port) {
// Not free. Try another.
continue
}
// We could bind to [port] so must be free.
_ = l.Close()
return port, nil
}
}
+4 -1
View File
@@ -81,6 +81,8 @@ type localNetworkOptions struct {
snapshotsDir string
logLevel logging.Level
reassignPortsIfUsed bool
}
func newLocalNetwork(opts localNetworkOptions) (*localNetwork, error) {
@@ -217,7 +219,7 @@ func (lc *localNetwork) start() error {
}
ux.Print(lc.log, logging.Blue.Wrap(logging.Bold.Wrap("create and run local network")))
nw, err := local.NewNetwork(lc.log, lc.cfg, lc.options.rootDataDir, lc.options.snapshotsDir)
nw, err := local.NewNetwork(lc.log, lc.cfg, lc.options.rootDataDir, lc.options.snapshotsDir, lc.options.reassignPortsIfUsed)
if err != nil {
return err
}
@@ -371,6 +373,7 @@ func (lc *localNetwork) loadSnapshot(
lc.options.chainConfigs,
lc.options.upgradeConfigs,
globalNodeConfig,
lc.options.reassignPortsIfUsed,
)
if err != nil {
return err