-
Notifications
You must be signed in to change notification settings - Fork 7
PCSM-219: Align all env var config with CLI and HTTP request options #165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
chupe
wants to merge
32
commits into
main
Choose a base branch
from
pcsm-219
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
69f0cfa
PCSM-219: Add Viper dependency and create config/config.go
chupe ffb345e
PCSM-219: Add CLI flag for MongoDB operation timeout (visible)
chupe 3f2ae63
PCSM-219: Add hidden CLI flag for bulk write option
chupe 94a83ca
PCSM-219: Add hidden CLI flags for clone tuning options (no env var)
chupe 230d759
PCSM-219: Add validator/v10 and create validation package
chupe 7b41462
PCSM-219: Add config/config.go
chupe fe51882
PCSM-219: Extend StartOptions and HTTP startRequest with validation
chupe 74b3a89
PCSM-219: Update README with configuration documentation
chupe 9ef4de1
Fix .vscode/settings.json formatting conflict
chupe e358ba1
PCSM-219: Simplify port flag handling with Viper
chupe cd7ffc1
PCSM-219: Consolidate configuration documentation
chupe be65433
PCSM-219: Remove external decision references from comments
chupe 7547453
PCSM-219: Remove unnecessary Viper wrappers
chupe 7133a98
PCSM-219: Move to mapstruct for config
chupe 1ae84b6
PCSM-219: Use embedded options for Clone and Repl
chupe 2b30ea2
PCSM-219: Undo README changes
chupe 2a0e34c
PCSM-219: Undoing using the validator
chupe aed7710
PCSM-219: Add integration tests for the CLI client
chupe c401994
PCSM-219: Move clone flags to start subcommand
chupe 37ac3df
Merge branch 'main' into pcsm-219
inelpandzic 9deb753
PCSM-219: Align config options with Notion spec
chupe 0504347
PCSM-219: Integrate target compressors into Viper config
chupe da314d6
PCSM-219: Remove manual timeout parsing
chupe eed97ff
PCSM-219: Reintroduce env vars for clone options
chupe 9c12910
PCSM-219: Consolidate naming for log no-color option
chupe 1255d8f
PCSM-219: Add backward compatible --no-color
chupe e0db093
PCSM-219: Address code location comments
chupe b8793b0
PCSM-219: Move config validation from runServer to rootCmd.RunE
chupe 492fb3c
PCSM-219: Remove viper calls from main.go
chupe 6a3ccfa
PCSM-219: Remove clone options flag reading
chupe 1bb77f5
PCSM-219: Add tests for start subcommand
chupe 14affd6
Merge branch 'main' into pcsm-219
inelpandzic File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| // Package config provides configuration management for PCSM using Viper. | ||
| package config | ||
|
|
||
| import ( | ||
| "math" | ||
| "slices" | ||
| "strings" | ||
| "time" | ||
|
|
||
| "github.com/dustin/go-humanize" | ||
| "github.com/go-viper/mapstructure/v2" | ||
| "github.com/spf13/cobra" | ||
| "github.com/spf13/viper" | ||
|
|
||
| "github.com/percona/percona-clustersync-mongodb/errors" | ||
| ) | ||
|
|
||
| // Config holds all PCSM configuration. | ||
| type Config struct { | ||
| Port int `mapstructure:"port"` | ||
| Source string `mapstructure:"source"` | ||
| Target string `mapstructure:"target"` | ||
|
|
||
| Log LogConfig `mapstructure:",squash"` | ||
|
|
||
| MongoDB MongoDBConfig `mapstructure:",squash"` | ||
|
|
||
| UseCollectionBulkWrite bool `mapstructure:"use-collection-bulk-write"` | ||
|
|
||
| Clone CloneConfig `mapstructure:",squash"` | ||
|
|
||
| // hidden startup flags | ||
| Start bool `mapstructure:"start"` | ||
| ResetState bool `mapstructure:"reset-state"` | ||
| PauseOnInitialSync bool `mapstructure:"pause-on-initial-sync"` | ||
| } | ||
|
|
||
| // LogConfig holds logging configuration. | ||
| type LogConfig struct { | ||
| Level string `mapstructure:"log-level"` | ||
| JSON bool `mapstructure:"log-json"` | ||
| NoColor bool `mapstructure:"log-no-color"` | ||
| } | ||
|
|
||
| // MongoDBConfig holds MongoDB client configuration. | ||
| type MongoDBConfig struct { | ||
| OperationTimeout time.Duration `mapstructure:"mongodb-operation-timeout"` | ||
| TargetCompressors []string `mapstructure:"dev-target-client-compressors"` | ||
| } | ||
|
|
||
| // CloneConfig holds clone operation configuration. | ||
| type CloneConfig struct { | ||
| // NumParallelCollections is the number of collections to clone in parallel. | ||
| // 0 means auto (calculated at runtime). | ||
| NumParallelCollections int `mapstructure:"clone-num-parallel-collections"` | ||
| // NumReadWorkers is the number of read workers during clone. | ||
| // 0 means auto (calculated at runtime). | ||
| NumReadWorkers int `mapstructure:"clone-num-read-workers"` | ||
| // NumInsertWorkers is the number of insert workers during clone. | ||
| // 0 means auto (calculated at runtime). | ||
| NumInsertWorkers int `mapstructure:"clone-num-insert-workers"` | ||
| // SegmentSize is the segment size for clone operations (e.g., "500MB", "1GiB"). | ||
| // Empty string means auto (calculated at runtime for each collection). | ||
| SegmentSize string `mapstructure:"clone-segment-size"` | ||
| // ReadBatchSize is the read batch size during clone (e.g., "16MiB", "100MB"). | ||
| // Empty string means auto (calculated at runtime for each collection). | ||
| ReadBatchSize string `mapstructure:"clone-read-batch-size"` | ||
| } | ||
|
|
||
| // Load initializes Viper and returns a validated Config. | ||
| func Load(cmd *cobra.Command) (*Config, error) { | ||
| viper.SetEnvPrefix("PCSM") | ||
| viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) | ||
| viper.AutomaticEnv() | ||
|
|
||
| if cmd.PersistentFlags() != nil { | ||
| _ = viper.BindPFlags(cmd.PersistentFlags()) | ||
| } | ||
|
|
||
| if cmd.Flags() != nil { | ||
| _ = viper.BindPFlags(cmd.Flags()) | ||
| } | ||
|
|
||
| bindEnvVars() | ||
|
|
||
| var cfg Config | ||
|
|
||
| err := viper.Unmarshal(&cfg, viper.DecodeHook( | ||
| mapstructure.ComposeDecodeHookFunc( | ||
| mapstructure.StringToTimeDurationHookFunc(), | ||
| mapstructure.StringToSliceHookFunc(","), | ||
| ), | ||
| )) | ||
| if err != nil { | ||
| return nil, errors.Wrap(err, "unmarshal config") | ||
| } | ||
|
|
||
| cfg.MongoDB.TargetCompressors = filterCompressors(cfg.MongoDB.TargetCompressors) | ||
|
|
||
| if viper.GetBool("no-color") { | ||
| cfg.Log.NoColor = true | ||
| } | ||
|
|
||
| return &cfg, nil | ||
| } | ||
|
|
||
| func bindEnvVars() { | ||
| _ = viper.BindEnv("port", "PCSM_PORT") | ||
|
|
||
| _ = viper.BindEnv("source", "PCSM_SOURCE_URI") | ||
| _ = viper.BindEnv("target", "PCSM_TARGET_URI") | ||
|
|
||
| _ = viper.BindEnv("log-level", "PCSM_LOG_LEVEL") | ||
| _ = viper.BindEnv("log-json", "PCSM_LOG_JSON") | ||
| _ = viper.BindEnv("log-no-color", "PCSM_LOG_NO_COLOR", "PCSM_NO_COLOR") | ||
|
|
||
| _ = viper.BindEnv("mongodb-operation-timeout", "PCSM_MONGODB_OPERATION_TIMEOUT") | ||
|
|
||
| _ = viper.BindEnv("use-collection-bulk-write", "PCSM_USE_COLLECTION_BULK_WRITE") | ||
|
|
||
| _ = viper.BindEnv("dev-target-client-compressors", "PCSM_DEV_TARGET_CLIENT_COMPRESSORS") | ||
|
|
||
| _ = viper.BindEnv("clone-num-parallel-collections", "PCSM_CLONE_NUM_PARALLEL_COLLECTIONS") | ||
| _ = viper.BindEnv("clone-num-read-workers", "PCSM_CLONE_NUM_READ_WORKERS") | ||
| _ = viper.BindEnv("clone-num-insert-workers", "PCSM_CLONE_NUM_INSERT_WORKERS") | ||
| _ = viper.BindEnv("clone-segment-size", "PCSM_CLONE_SEGMENT_SIZE") | ||
| _ = viper.BindEnv("clone-read-batch-size", "PCSM_CLONE_READ_BATCH_SIZE") | ||
| } | ||
|
|
||
| //nolint:gochecknoglobals | ||
| var allowedCompressors = []string{"zstd", "zlib", "snappy"} | ||
|
|
||
| func filterCompressors(compressors []string) []string { | ||
| if len(compressors) == 0 { | ||
| return nil | ||
| } | ||
|
|
||
| filtered := make([]string, 0, len(allowedCompressors)) | ||
|
|
||
| for _, c := range compressors { | ||
| c = strings.TrimSpace(c) | ||
| if slices.Contains(allowedCompressors, c) && !slices.Contains(filtered, c) { | ||
| filtered = append(filtered, c) | ||
| } | ||
| } | ||
|
|
||
| return filtered | ||
| } | ||
|
|
||
| // ParseAndValidateCloneSegmentSize parses a byte size string and validates it. | ||
| // It allows 0 (auto) or values within [MinCloneSegmentSizeBytes, MaxCloneSegmentSizeBytes]. | ||
| func ParseAndValidateCloneSegmentSize(value string) (int64, error) { | ||
| sizeBytes, err := humanize.ParseBytes(value) | ||
| if err != nil { | ||
| return 0, errors.Wrapf(err, "invalid cloneSegmentSize value: %s", value) | ||
| } | ||
|
|
||
| err = ValidateCloneSegmentSize(sizeBytes) | ||
| if err != nil { | ||
| return 0, err | ||
| } | ||
|
|
||
| return int64(min(sizeBytes, math.MaxInt64)), nil //nolint:gosec | ||
| } | ||
|
|
||
| // ParseAndValidateCloneReadBatchSize parses a byte size string and validates it. | ||
| // It allows 0 (auto) or values within [[MinCloneReadBatchSizeBytes], [MaxCloneReadBatchSizeBytes]]. | ||
| func ParseAndValidateCloneReadBatchSize(value string) (int32, error) { | ||
| sizeBytes, err := humanize.ParseBytes(value) | ||
| if err != nil { | ||
| return 0, errors.Wrapf(err, "invalid cloneReadBatchSize value: %s", value) | ||
| } | ||
|
|
||
| err = ValidateCloneReadBatchSize(sizeBytes) | ||
| if err != nil { | ||
| return 0, err | ||
| } | ||
|
|
||
| return int32(min(sizeBytes, math.MaxInt32)), nil //nolint:gosec | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.