diff --git a/services/horizon/internal/environment.go b/services/horizon/internal/environment.go new file mode 100644 index 0000000000..ab1193d680 --- /dev/null +++ b/services/horizon/internal/environment.go @@ -0,0 +1,65 @@ +package horizon + +import ( + "fmt" + "os" + "strings" + + "github.com/stellar/go/support/errors" +) + +type EnvironmentManager struct { + oldEnvironment, newEnvironment map[string]string +} + +func NewEnvironmentManager() *EnvironmentManager { + env := &EnvironmentManager{} + env.oldEnvironment = make(map[string]string) + env.newEnvironment = make(map[string]string) + return env +} + +func (envManager *EnvironmentManager) InitializeEnvironmentVariables(environmentVars map[string]string) error { + var env strings.Builder + for key, value := range environmentVars { + env.WriteString(fmt.Sprintf("%s=%s ", key, value)) + } + + // prepare env + for key, value := range environmentVars { + innerErr := envManager.Add(key, value) + if innerErr != nil { + return errors.Wrap(innerErr, fmt.Sprintf( + "failed to set envvar (%s=%s)", key, value)) + } + } + return nil +} + +// Add sets a new environment variable, saving the original value (if any). +func (envManager *EnvironmentManager) Add(key, value string) error { + // If someone pushes an environmental variable more than once, we don't want + // to lose the *original* value, so we're being careful here. + if _, ok := envManager.newEnvironment[key]; !ok { + if oldValue, ok := os.LookupEnv(key); ok { + envManager.oldEnvironment[key] = oldValue + } + } + + envManager.newEnvironment[key] = value + return os.Setenv(key, value) +} + +// Restore restores the environment prior to any modifications. +// +// You should probably use this alongside `defer` to ensure the global +// environment isn't modified for longer than you intend. +func (envManager *EnvironmentManager) Restore() { + for key := range envManager.newEnvironment { + if oldValue, ok := envManager.oldEnvironment[key]; ok { + os.Setenv(key, oldValue) + } else { + os.Unsetenv(key) + } + } +} diff --git a/services/horizon/internal/flags_test.go b/services/horizon/internal/flags_test.go index 38e0c16bda..5fc42d898f 100644 --- a/services/horizon/internal/flags_test.go +++ b/services/horizon/internal/flags_test.go @@ -2,6 +2,8 @@ package horizon import ( "fmt" + "github.com/spf13/cobra" + "os" "testing" "github.com/stretchr/testify/assert" @@ -131,3 +133,55 @@ func Test_createCaptiveCoreConfig(t *testing.T) { }) } } + +func TestEnvironmentVariables(t *testing.T) { + environmentVars := map[string]string{ + "INGEST": "false", + "HISTORY_ARCHIVE_URLS": "http://localhost:1570", + "DATABASE_URL": "postgres://postgres@localhost/test_332cb65e6b00?sslmode=disable&timezone=UTC", + "STELLAR_CORE_URL": "http://localhost:11626", + "NETWORK_PASSPHRASE": "Standalone Network ; February 2017", + "APPLY_MIGRATIONS": "true", + "ENABLE_CAPTIVE_CORE_INGESTION": "false", + "CHECKPOINT_FREQUENCY": "8", + "MAX_DB_CONNECTIONS": "50", + "ADMIN_PORT": "6060", + "PORT": "8001", + "CAPTIVE_CORE_BINARY_PATH": os.Getenv("HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_BIN"), + "CAPTIVE_CORE_CONFIG_PATH": "../docker/captive-core-classic-integration-tests.cfg", + "CAPTIVE_CORE_USE_DB": "true", + } + envManager := NewEnvironmentManager() + if err := envManager.InitializeEnvironmentVariables(environmentVars); err != nil { + fmt.Println(err) + } + config, flags := Flags() + horizonCmd := &cobra.Command{ + Use: "horizon", + Short: "Client-facing api server for the Stellar network", + SilenceErrors: true, + SilenceUsage: true, + Long: "Client-facing API server for the Stellar network.", + } + if err := flags.Init(horizonCmd); err != nil { + fmt.Println(err) + } + if err := ApplyFlags(config, flags, ApplyOptions{RequireCaptiveCoreConfig: true, AlwaysIngest: false}); err != nil { + fmt.Println(err) + } + assert.Equal(t, config.Ingest, false) + assert.Equal(t, config.HistoryArchiveURLs, []string{"http://localhost:1570"}) + assert.Equal(t, config.DatabaseURL, "postgres://postgres@localhost/test_332cb65e6b00?sslmode=disable&timezone=UTC") + assert.Equal(t, config.StellarCoreURL, "http://localhost:11626") + assert.Equal(t, config.NetworkPassphrase, "Standalone Network ; February 2017") + assert.Equal(t, config.ApplyMigrations, true) + assert.Equal(t, config.EnableCaptiveCoreIngestion, false) + assert.Equal(t, config.CheckpointFrequency, uint32(8)) + assert.Equal(t, config.MaxDBConnections, 50) + assert.Equal(t, config.AdminPort, uint(6060)) + assert.Equal(t, config.Port, uint(8001)) + assert.Equal(t, config.CaptiveCoreBinaryPath, os.Getenv("HORIZON_INTEGRATION_TESTS_CAPTIVE_CORE_BIN")) + assert.Equal(t, config.CaptiveCoreConfigPath, "../docker/captive-core-classic-integration-tests.cfg") + assert.Equal(t, config.CaptiveCoreConfigUseDB, true) + envManager.Restore() +} diff --git a/services/horizon/internal/integration/parameters_test.go b/services/horizon/internal/integration/parameters_test.go index 0958063ae4..5917320000 100644 --- a/services/horizon/internal/integration/parameters_test.go +++ b/services/horizon/internal/integration/parameters_test.go @@ -431,12 +431,6 @@ func TestDisableTxSub(t *testing.T) { test.Shutdown() }) t.Run("horizon starts successfully when DISABLE_TX_SUB=true and INGEST=true", func(t *testing.T) { - //localParams := integration.MergeMaps(networkParamArgs, map[string]string{ - // //horizon.NetworkFlagName: "testnet", - // horizon.IngestFlagName: "true", - // horizon.DisableTxSubFlagName: "true", - // horizon.StellarCoreBinaryPathName: "/usr/bin/stellar-core", - //}) testConfig := integration.GetTestConfig() testConfig.HorizonIngestParameters = map[string]string{ "disable-tx-sub": "true",