Repository: etcd-io/etcd
File: server/etcdmain/config.go (Go)

Code before:
	err = embed.SetFeatureGatesFromExperimentalFlags(cfg.ec.ServerFeatureGate, cfg.getBoolFlagVal, embed.ServerFeatureGateFlagName, cfg.cf.flagSet.Lookup(embed.ServerFeatureGateFlagName).Value.String())
	if err != nil {
		return err
	}

	return cfg.validate()
}

// getBoolFlagVal returns the value of the a given bool flag is explicitly set in the cmd line arguments,
// and returns nil if it is not explicitly set.
func (cfg *config) getBoolFlagVal(flagName string) *bool {
	explicitlySet := false
	cfg.cf.flagSet.Visit(func(f *flag.Flag) {
		if f.Name == flagName {
			explicitlySet = true
		}
	})
	if !explicitlySet {
		return nil
	}
	flagVal, parseErr := strconv.ParseBool(cfg.cf.flagSet.Lookup(flagName).Value.String())
	if parseErr != nil {
		panic(parseErr)
	}
	return &flagVal
}

func (cfg *config) configFromFile(path string) error {
	eCfg, err := embed.ConfigFromFile(path)
	if err != nil {
		return err
	}
	// TODO: remove after adding feature-gates field in the config file.
	if eCfg.ExperimentalStopGRPCServiceOnDefrag {
		eCfg.ServerFeatureGate.(featuregate.MutableFeatureGate).Set("StopGRPCServiceOnDefrag=true")
	}
	cfg.ec = *eCfg

	return nil
}

func (cfg *config) validate() error {
	if cfg.cf.fallback.String() == fallbackFlagProxy {
		return fmt.Errorf("v2 proxy is deprecated, and --discovery-fallback can't be configured as %q", fallbackFlagProxy)
	}
	return cfg.ec.Validate()
}

func (cfg *config) parseWarningUnaryRequestDuration() (time.Duration, error) {
	if cfg.ec.ExperimentalWarningUnaryRequestDuration != 0 && cfg.ec.WarningUnaryRequestDuration != 0 {
		return 0, errors.New(

Review comment (refactor):
We can move this into https://github.com/etcd-io/etcd/blob/main/pkg/flags/flag.go as a generic function something like below,

```
func GetBoolFlagVal(fs *flag.FlagSet, flagName string) *bool {
    ......
}
```

Code after:
	// SetFeatureGatesFromExperimentalFlags validates that cmd line flags for experimental feature and their feature gates are not explicitly set simultaneously,
	// and passes the values of cmd line flags for experimental feature to the server feature gate.
	err = embed.SetFeatureGatesFromExperimentalFlags(cfg.ec.ServerFeatureGate, getBoolFlagVal, cfg.cf.flagSet.Lookup(embed.ServerFeatureGateFlagName).Value.String())
	if err != nil {
		return err
	}

	return cfg.validate()
}

func (cfg *config) configFromFile(path string) error {
	eCfg, err := embed.ConfigFromFile(path)
	if err != nil {
		return err
	}
	cfg.ec = *eCfg

	return nil
}

func (cfg *config) validate() error {
	if cfg.cf.fallback.String() == fallbackFlagProxy {
		return fmt.Errorf("v2 proxy is deprecated, and --discovery-fallback can't be configured as %q", fallbackFlagProxy)
	}
	return cfg.ec.Validate()
}

func (cfg *config) parseWarningUnaryRequestDuration() (time.Duration, error) {
	if cfg.ec.ExperimentalWarningUnaryRequestDuration != 0 && cfg.ec.WarningUnaryRequestDuration != 0 {
		return 0, errors.New(
			"both --experimental-warning-unary-request-duration and --warning-unary-request-duration flags are set. " +
				"Use only --warning-unary-request-duration")
	}

	if cfg.ec.WarningUnaryRequestDuration != 0 {
		return cfg.ec.WarningUnaryRequestDuration, nil
	}

	if cfg.ec.ExperimentalWarningUnaryRequestDuration != 0 {
		cfg.ec.GetLogger().Warn(
			"--experimental-warning-unary-request-duration is deprecated, and will be decommissioned in v3.7. " +
				"Use --warning-unary-request-duration instead.")
		return cfg.ec.ExperimentalWarningUnaryRequestDuration, nil
	}

	return embed.DefaultWarningUnaryRequestDuration, nil
}