diff --git a/internal/config/global.go b/internal/config/global.go index 4bc5ac3d2..57af89d05 100644 --- a/internal/config/global.go +++ b/internal/config/global.go @@ -52,3 +52,9 @@ func LoadEarlyFlags(cmd *cobra.Command) error { func BindFlags(cmd *cobra.Command) error { return global.BindFlags(cmd) } + +// Reset will totally clear global +// ConfigState{}, loading defaults. +func Reset() { + global.Reset() +} diff --git a/internal/config/state.go b/internal/config/state.go index c55f7b2ec..d01e853a5 100644 --- a/internal/config/state.go +++ b/internal/config/state.go @@ -37,25 +37,9 @@ type ConfigState struct { //nolint // NewState returns a new initialized ConfigState instance. func NewState() *ConfigState { - viper := viper.New() - - // Flag 'some-flag-name' becomes env var 'GTS_SOME_FLAG_NAME' - viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) - viper.SetEnvPrefix("gts") - - // Load appropriate named vals from env - viper.AutomaticEnv() - - // Create new ConfigState with defaults - state := &ConfigState{ - viper: viper, - config: Defaults, - } - - // Perform initial load into viper - state.reloadToViper() - - return state + st := new(ConfigState) + st.Reset() + return st } // Config provides safe access to the ConfigState's contained Configuration, @@ -116,6 +100,32 @@ func (st *ConfigState) Reload() (err error) { return } +// Reset will totally clear +// ConfigState{}, loading defaults. +func (st *ConfigState) Reset() { + // Do within lock. + st.mutex.Lock() + defer st.mutex.Unlock() + + // Create new viper. + viper := viper.New() + + // Flag 'some-flag-name' becomes env var 'GTS_SOME_FLAG_NAME' + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + viper.SetEnvPrefix("gts") + + // Load appropriate + // named vals from env. + viper.AutomaticEnv() + + // Reset variables. + st.viper = viper + st.config = Defaults + + // Load into viper. + st.reloadToViper() +} + // reloadToViper will reload Configuration{} values into viper. func (st *ConfigState) reloadToViper() { raw, err := st.config.MarshalMap() diff --git a/internal/db/postgres/driver.go b/internal/db/postgres/driver.go index b0bfc53b1..994c9ffba 100644 --- a/internal/db/postgres/driver.go +++ b/internal/db/postgres/driver.go @@ -29,10 +29,10 @@ var ( // global PostgreSQL driver instances. postgresDriver = pgx.GetDefaultDriver().(*pgx.Driver) - // check the postgres connection - // conforms to our conn{} interface. + // check the postgres driver types + // conforms to our interface types. // (note SQLite doesn't export their - // conn type, and gets checked in + // driver types, and gets checked in // tests very regularly anywho). _ connIface = (*pgx.Conn)(nil) _ stmtIface = (*pgx.Stmt)(nil) diff --git a/testrig/config.go b/testrig/config.go index 8b69b714c..4835d03b7 100644 --- a/testrig/config.go +++ b/testrig/config.go @@ -19,143 +19,164 @@ package testrig import ( "os" + "strconv" "time" + // linkname shenanigans + _ "unsafe" + "codeberg.org/gruf/go-bytesize" "github.com/coreos/go-oidc/v3/oidc" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/language" ) -// InitTestConfig initializes viper configuration with test defaults. +// initialize with test defaults. +func init() { InitTestConfig() } + +// InitTestConfig initializes viper +// configuration with test defaults. func InitTestConfig() { - config.Config(func(cfg *config.Configuration) { - *cfg = testDefaults + config.Defaults = testDefaults() + config.Reset() +} + +func testDefaults() config.Configuration { + return config.Configuration{ + LogLevel: envStr("GTS_LOG_LEVEL", "error"), + LogTimestampFormat: "02/01/2006 15:04:05.000", + LogDbQueries: true, + ApplicationName: "gotosocial", + LandingPageUser: "", + ConfigPath: "", + Host: "localhost:8080", + AccountDomain: "localhost:8080", + Protocol: "http", + BindAddress: "127.0.0.1", + Port: 8080, + TrustedProxies: []string{"127.0.0.1/32", "::1"}, + DbType: envStr("GTS_DB_TYPE", "sqlite"), + DbAddress: envStr("GTS_DB_ADDRESS", ":memory:"), + DbPort: envInt("GTS_DB_PORT", 5432), + DbUser: envStr("GTS_DB_USER", "postgres"), + DbPassword: envStr("GTS_DB_PASSWORD", "postgres"), + DbDatabase: envStr("GTS_DB_DATABASE", "postgres"), + DbTLSMode: envStr("GTS_DB_TLS_MODE", "disable"), + DbTLSCACert: envStr("GTS_DB_TLS_CA_CERT", ""), + DbMaxOpenConnsMultiplier: 1, + DbSqliteJournalMode: "WAL", + DbSqliteSynchronous: "NORMAL", + DbSqliteCacheSize: 8 * bytesize.MiB, + DbSqliteBusyTimeout: time.Minute * 5, + + WebTemplateBaseDir: "./web/template/", + WebAssetBaseDir: "./web/assets/", + + InstanceFederationMode: config.InstanceFederationModeDefault, + InstanceFederationSpamFilter: true, + InstanceExposePeers: true, + InstanceExposeSuspended: true, + InstanceExposeSuspendedWeb: true, + InstanceDeliverToSharedInboxes: true, + InstanceLanguages: language.Languages{ + { + TagStr: "nl", + }, + { + TagStr: "en-gb", + }, + }, + + AccountsRegistrationOpen: true, + AccountsReasonRequired: true, + AccountsAllowCustomCSS: true, + AccountsCustomCSSLength: 10000, + + MediaImageMaxSize: 10485760, // 10MiB + MediaVideoMaxSize: 41943040, // 40MiB + MediaDescriptionMinChars: 0, + MediaDescriptionMaxChars: 500, + MediaRemoteCacheDays: 7, + MediaEmojiLocalMaxSize: 51200, // 50KiB + MediaEmojiRemoteMaxSize: 102400, // 100KiB + MediaCleanupFrom: "00:00", // midnight. + MediaCleanupEvery: 24 * time.Hour, // 1/day. + + // the testrig only uses in-memory storage, so we can + // safely set this value to 'test' to avoid running storage + // migrations, and other silly things like that + StorageBackend: "test", + StorageLocalBasePath: "", + + StatusesMaxChars: 5000, + StatusesPollMaxOptions: 6, + StatusesPollOptionMaxChars: 50, + StatusesMediaMaxFiles: 6, + + LetsEncryptEnabled: false, + LetsEncryptPort: 0, + LetsEncryptCertDir: "", + LetsEncryptEmailAddress: "", + + OIDCEnabled: false, + OIDCIdpName: "", + OIDCSkipVerification: false, + OIDCIssuer: "", + OIDCClientID: "", + OIDCClientSecret: "", + OIDCScopes: []string{oidc.ScopeOpenID, "profile", "email", "groups"}, + OIDCLinkExisting: false, + OIDCAdminGroups: []string{"adminRole"}, + OIDCAllowedGroups: []string{"allowedRole"}, + + SMTPHost: "", + SMTPPort: 0, + SMTPUsername: "", + SMTPPassword: "", + SMTPFrom: "GoToSocial", + SMTPDiscloseRecipients: false, + + TracingEnabled: false, + TracingEndpoint: "localhost:4317", + TracingTransport: "grpc", + TracingInsecureTransport: true, + + MetricsEnabled: false, + MetricsAuthEnabled: false, + + SyslogEnabled: false, + SyslogProtocol: "udp", + SyslogAddress: "localhost:514", + + AdvancedCookiesSamesite: "lax", + AdvancedRateLimitRequests: 0, // disabled + AdvancedThrottlingMultiplier: 0, // disabled + AdvancedSenderMultiplier: 0, // 1 sender only, regardless of CPU + + SoftwareVersion: "0.0.0-testrig", + + // simply use cache defaults. + Cache: config.Defaults.Cache, + } +} + +func envInt(key string, _default int) int { + return env(key, _default, func(value string) int { + i, _ := strconv.Atoi(value) + return i }) } -func logLevel() string { - level := "error" - if lv := os.Getenv("GTS_LOG_LEVEL"); lv != "" { - level = lv +func envStr(key string, _default string) string { + return env(key, _default, func(value string) string { + return value + }) +} + +func env[T any](key string, _default T, parse func(string) T) T { + value, ok := os.LookupEnv(key) + if ok { + return parse(value) } - return level -} - -var testDefaults = config.Configuration{ - LogLevel: logLevel(), - LogTimestampFormat: "02/01/2006 15:04:05.000", - LogDbQueries: true, - ApplicationName: "gotosocial", - LandingPageUser: "", - ConfigPath: "", - Host: "localhost:8080", - AccountDomain: "localhost:8080", - Protocol: "http", - BindAddress: "127.0.0.1", - Port: 8080, - TrustedProxies: []string{"127.0.0.1/32", "::1"}, - - DbType: "sqlite", - DbAddress: ":memory:", - DbPort: 5432, - DbUser: "postgres", - DbPassword: "postgres", - DbDatabase: "postgres", - DbTLSMode: "disable", - DbTLSCACert: "", - DbMaxOpenConnsMultiplier: 8, - DbSqliteJournalMode: "WAL", - DbSqliteSynchronous: "NORMAL", - DbSqliteCacheSize: 8 * bytesize.MiB, - DbSqliteBusyTimeout: time.Minute * 5, - - WebTemplateBaseDir: "./web/template/", - WebAssetBaseDir: "./web/assets/", - - InstanceFederationMode: config.InstanceFederationModeDefault, - InstanceFederationSpamFilter: true, - InstanceExposePeers: true, - InstanceExposeSuspended: true, - InstanceExposeSuspendedWeb: true, - InstanceDeliverToSharedInboxes: true, - InstanceLanguages: language.Languages{ - { - TagStr: "nl", - }, - { - TagStr: "en-gb", - }, - }, - - AccountsRegistrationOpen: true, - AccountsReasonRequired: true, - AccountsAllowCustomCSS: true, - AccountsCustomCSSLength: 10000, - - MediaImageMaxSize: 10485760, // 10MiB - MediaVideoMaxSize: 41943040, // 40MiB - MediaDescriptionMinChars: 0, - MediaDescriptionMaxChars: 500, - MediaRemoteCacheDays: 7, - MediaEmojiLocalMaxSize: 51200, // 50KiB - MediaEmojiRemoteMaxSize: 102400, // 100KiB - MediaCleanupFrom: "00:00", // midnight. - MediaCleanupEvery: 24 * time.Hour, // 1/day. - - // the testrig only uses in-memory storage, so we can - // safely set this value to 'test' to avoid running storage - // migrations, and other silly things like that - StorageBackend: "test", - StorageLocalBasePath: "", - - StatusesMaxChars: 5000, - StatusesPollMaxOptions: 6, - StatusesPollOptionMaxChars: 50, - StatusesMediaMaxFiles: 6, - - LetsEncryptEnabled: false, - LetsEncryptPort: 0, - LetsEncryptCertDir: "", - LetsEncryptEmailAddress: "", - - OIDCEnabled: false, - OIDCIdpName: "", - OIDCSkipVerification: false, - OIDCIssuer: "", - OIDCClientID: "", - OIDCClientSecret: "", - OIDCScopes: []string{oidc.ScopeOpenID, "profile", "email", "groups"}, - OIDCLinkExisting: false, - OIDCAdminGroups: []string{"adminRole"}, - OIDCAllowedGroups: []string{"allowedRole"}, - - SMTPHost: "", - SMTPPort: 0, - SMTPUsername: "", - SMTPPassword: "", - SMTPFrom: "GoToSocial", - SMTPDiscloseRecipients: false, - - TracingEnabled: false, - TracingEndpoint: "localhost:4317", - TracingTransport: "grpc", - TracingInsecureTransport: true, - - MetricsEnabled: false, - MetricsAuthEnabled: false, - - SyslogEnabled: false, - SyslogProtocol: "udp", - SyslogAddress: "localhost:514", - - AdvancedCookiesSamesite: "lax", - AdvancedRateLimitRequests: 0, // disabled - AdvancedThrottlingMultiplier: 0, // disabled - AdvancedSenderMultiplier: 0, // 1 sender only, regardless of CPU - - SoftwareVersion: "0.0.0-testrig", - - // simply use cache defaults. - Cache: config.Defaults.Cache, + return _default } diff --git a/testrig/db.go b/testrig/db.go index 83bc46ec8..1e5419b7e 100644 --- a/testrig/db.go +++ b/testrig/db.go @@ -19,10 +19,7 @@ package testrig import ( "context" - "os" - "strconv" - "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/db/bundb" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -84,22 +81,6 @@ var testModels = []interface{}{ // If the environment variable GTS_DB_PORT is set, it will take that // value as the port instead. func NewTestDB(state *state.State) db.DB { - if alternateAddress := os.Getenv("GTS_DB_ADDRESS"); alternateAddress != "" { - config.SetDbAddress(alternateAddress) - } - - if alternateDBType := os.Getenv("GTS_DB_TYPE"); alternateDBType != "" { - config.SetDbType(alternateDBType) - } - - if alternateDBPort := os.Getenv("GTS_DB_PORT"); alternateDBPort != "" { - port, err := strconv.ParseUint(alternateDBPort, 10, 16) - if err != nil { - panic(err) - } - config.SetDbPort(int(port)) - } - state.Caches.Init() testDB, err := bundb.NewBunDBService(context.Background(), state)