package nodeconfig import ( "fmt" "io/fs" "os" "strconv" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" utilConfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) // PersistentSessionsConfig is a wrapper over "persistent_sessions" config section // which provides access to persistent session tokens storage configuration of node. type PersistentSessionsConfig struct { cfg *config.Config } // PersistentStateConfig is a wrapper over "persistent_state" config section // which provides access to persistent state storage configuration of node. type PersistentStateConfig struct { cfg *config.Config } // NotificationConfig is a wrapper over "notification" config section // which provides access to object notification configuration of node. type NotificationConfig struct { cfg *config.Config } // PersistentPolicyRulesConfig is a wrapper over "persistent_policy_rules" config section // which provides access to persistent policy rules storage configuration of node. type PersistentPolicyRulesConfig struct { cfg *config.Config } const ( subsection = "node" persistentSessionsSubsection = "persistent_sessions" persistentStateSubsection = "persistent_state" notificationSubsection = "notification" persistentPolicyRulesSubsection = "persistent_policy_rules" attributePrefix = "attribute" // PersistentStatePathDefault is a default path for persistent state file. PersistentStatePathDefault = ".frostfs-storage-state" // NotificationTimeoutDefault is a default timeout for object notification operation. NotificationTimeoutDefault = 5 * time.Second ) // Key returns the value of "key" config parameter // from "node" section. // // If the value is not set, fallbacks to Wallet section. // // Panics if the value is incorrect filename of binary encoded private key. func Key(c *config.Config) *keys.PrivateKey { v := config.StringSafe(c.Sub(subsection), "key") if v == "" { return Wallet(c) } var ( key *keys.PrivateKey err error data []byte ) if data, err = os.ReadFile(v); err == nil { key, err = keys.NewPrivateKeyFromBytes(data) } if err != nil { panic(fmt.Errorf("invalid private key in node section: %w", err)) } return key } // Wallet returns the value of a node private key from "node" section. // // Panics if section contains invalid values. func Wallet(c *config.Config) *keys.PrivateKey { v := c.Sub(subsection).Sub("wallet") acc, err := utilConfig.LoadAccount( config.String(v, "path"), config.String(v, "address"), config.String(v, "password")) if err != nil { panic(fmt.Errorf("invalid wallet config: %w", err)) } return acc.PrivateKey() } type stringAddressGroup []string func (x stringAddressGroup) IterateAddresses(f func(string) bool) { for i := range x { if f(x[i]) { break } } } func (x stringAddressGroup) NumberOfAddresses() int { return len(x) } // BootstrapAddresses returns the value of "addresses" config parameter // from "node" section as network.AddressGroup. // // Panics if the value is not a string list of valid NeoFS network addresses. func BootstrapAddresses(c *config.Config) (addr network.AddressGroup) { v := config.StringSlice(c.Sub(subsection), "addresses") err := addr.FromIterator(stringAddressGroup(v)) if err != nil { panic(fmt.Errorf("could not parse bootstrap addresses: %w", err)) } return addr } // Attributes returns list of config parameters // from "node" section that are set in "attribute_i" format, // where i in range [0,100). func Attributes(c *config.Config) (attrs []string) { const maxAttributes = 100 for i := 0; i < maxAttributes; i++ { attr := config.StringSafe(c.Sub(subsection), attributePrefix+"_"+strconv.Itoa(i)) if attr == "" { return } attrs = append(attrs, attr) } return } // Relay returns the value of "relay" config parameter // from "node" section. // // Returns false if the value is not set. func Relay(c *config.Config) bool { return config.BoolSafe(c.Sub(subsection), "relay") } // PersistentSessions returns structure that provides access to "persistent_sessions" // subsection of "node" section. func PersistentSessions(c *config.Config) PersistentSessionsConfig { return PersistentSessionsConfig{ c.Sub(subsection).Sub(persistentSessionsSubsection), } } // Path returns the value of "path" config parameter. func (p PersistentSessionsConfig) Path() string { return config.String(p.cfg, "path") } // PersistentState returns structure that provides access to "persistent_state" // subsection of "node" section. func PersistentState(c *config.Config) PersistentStateConfig { return PersistentStateConfig{ c.Sub(subsection).Sub(persistentStateSubsection), } } // Path returns the value of "path" config parameter. // // Returns PersistentStatePathDefault if the value is not a non-empty string. func (p PersistentStateConfig) Path() string { v := config.String(p.cfg, "path") if v != "" { return v } return PersistentStatePathDefault } // Notification returns structure that provides access to "notification" // subsection of "node" section. func Notification(c *config.Config) NotificationConfig { return NotificationConfig{ c.Sub(subsection).Sub(notificationSubsection), } } // Enabled returns the value of "enabled" config parameter from "notification" // subsection of "node" section. // // Returns false if the value is not presented. func (n NotificationConfig) Enabled() bool { return config.BoolSafe(n.cfg, "enabled") } // DefaultTopic returns the value of "default_topic" config parameter from // "notification" subsection of "node" section. // // Returns empty string if the value is not presented. func (n NotificationConfig) DefaultTopic() string { return config.StringSafe(n.cfg, "default_topic") } // Endpoint returns the value of "endpoint" config parameter from "notification" // subsection of "node" section. // // Returns empty string if the value is not presented. func (n NotificationConfig) Endpoint() string { return config.StringSafe(n.cfg, "endpoint") } // Timeout returns the value of "timeout" config parameter from "notification" // subsection of "node" section. // // Returns NotificationTimeoutDefault if the value is not positive. func (n NotificationConfig) Timeout() time.Duration { v := config.DurationSafe(n.cfg, "timeout") if v > 0 { return v } return NotificationTimeoutDefault } // CertPath returns the value of "certificate_path" config parameter from "notification" // subsection of "node" section. // // Returns empty string if the value is not presented. func (n NotificationConfig) CertPath() string { return config.StringSafe(n.cfg, "certificate") } // KeyPath returns the value of "key_path" config parameter from // "notification" subsection of "node" section. // // Returns empty string if the value is not presented. func (n NotificationConfig) KeyPath() string { return config.StringSafe(n.cfg, "key") } // CAPath returns the value of "ca_path" config parameter from // "notification" subsection of "node" section. // // Returns empty string if the value is not presented. func (n NotificationConfig) CAPath() string { return config.StringSafe(n.cfg, "ca") } const ( // PermDefault is a default permission bits for local override storage file. PermDefault = 0o644 ) // PersistentPolicyRules returns structure that provides access to "persistent_policy_rules" // subsection of "node" section. func PersistentPolicyRules(c *config.Config) PersistentPolicyRulesConfig { return PersistentPolicyRulesConfig{ c.Sub(subsection).Sub(persistentPolicyRulesSubsection), } } // Path returns the value of "path" config parameter. // // Returns empty string if missing, for compatibility with older configurations. func (l PersistentPolicyRulesConfig) Path() string { return config.StringSafe(l.cfg, "path") } // Perm returns the value of "perm" config parameter as a fs.FileMode. // // Returns PermDefault if the value is not a positive number. func (l PersistentPolicyRulesConfig) Perm() fs.FileMode { p := config.UintSafe((*config.Config)(l.cfg), "perm") if p == 0 { p = PermDefault } return fs.FileMode(p) } // NoSync returns the value of "no_sync" config parameter as a bool value. // // Returns false if the value is not a boolean. func (l PersistentPolicyRulesConfig) NoSync() bool { return config.BoolSafe((*config.Config)(l.cfg), "no_sync") } // CompatibilityMode returns true if need to run node in compatibility with previous versions mode. func CompatibilityMode(c *config.Config) bool { return config.BoolSafe(c.Sub(subsection), "kludge_compatibility_mode") }