From 7581132517ff5677fd05be98083062ca80a36c78 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Tue, 8 Aug 2023 18:20:03 -0500 Subject: [PATCH 1/3] improve set-env CLI cmd --- cmd/osmosisd/cmd/change_environment.go | 145 +++++++++++++++++++++---- cmd/osmosisd/cmd/root.go | 11 +- tests/e2e/e2e_test.go | 3 +- 3 files changed, 132 insertions(+), 27 deletions(-) diff --git a/cmd/osmosisd/cmd/change_environment.go b/cmd/osmosisd/cmd/change_environment.go index 56c51d18389..7e37fead924 100644 --- a/cmd/osmosisd/cmd/change_environment.go +++ b/cmd/osmosisd/cmd/change_environment.go @@ -5,6 +5,8 @@ import ( "os" "path/filepath" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/joho/godotenv" "github.com/spf13/cobra" @@ -14,7 +16,8 @@ import ( const ( EnvVariable = "OSMOSISD_ENVIRONMENT" EnvMainnet = "mainnet" - EnvLocalnet = "localosmosis" + EnvTestnet = "testnet" + EnvLocalnet = "localnet" ) // ExportAirdropSnapshotCmd generates a snapshot.json from a provided exported genesis.json. @@ -25,29 +28,18 @@ func ChangeEnvironmentCmd() *cobra.Command { Long: `Set home environment variables for commands Example: osmosisd set-env mainnet - osmosisd set-env localosmosis + osmosisd set-env testnet + osmosisd set-env localnet osmosisd set-env $HOME/.custom-dir `, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + // Note: If we are calling this method, the environment file has already been set in + // NewRootCmd() when creating the rootCmd. We do this because order of operations + // dictates this as a requirement. If we changed the env file here, the osmosis + // daemon would not initialize the folder we are intending to set to. newEnv := args[0] - - currentEnvironment := getHomeEnvironment() - fmt.Println("Current environment: ", currentEnvironment) - - if _, err := environmentNameToPath(newEnv); err != nil { - return err - } - - fmt.Println("New environment: ", newEnv) - - envMap := make(map[string]string) - envMap[EnvVariable] = newEnv - err := godotenv.Write(envMap, filepath.Join(app.DefaultNodeHome, ".env")) - if err != nil { - return err - } - return nil + return clientSettingsFromEnv(cmd, newEnv) }, } return cmd @@ -64,8 +56,8 @@ Example: Returns one of: - mainnet implying $HOME/.osmosisd + - testnet implying $HOME/.osmosisd-test - localosmosis implying $HOME/.osmosisd-local - - localosmosis - custom path`, RunE: func(cmd *cobra.Command, args []string) error { environment := getHomeEnvironment() @@ -91,17 +83,122 @@ func environmentNameToPath(environmentName string) (string, error) { switch environmentName { case EnvMainnet: return app.DefaultNodeHome, nil + case EnvTestnet: + return filepath.Join(userHomeDir, ".osmosisd-test/"), nil case EnvLocalnet: return filepath.Join(userHomeDir, ".osmosisd-local/"), nil default: - osmosisdPath := filepath.Join(userHomeDir, environmentName) - _, err := os.Stat(osmosisdPath) + _, err := os.Stat(environmentName) if os.IsNotExist(err) { // Creating new environment directory - if err := os.Mkdir(osmosisdPath, os.ModePerm); err != nil { + if err := os.Mkdir(environmentName, os.ModePerm); err != nil { return "", err } } - return osmosisdPath, nil + return environmentName, nil + } +} + +// clientSettingsFromEnv takes the env name (mainnet, testnet, localnet, etc) and sets the +// client.toml settings to commonly used values for that environment. +func clientSettingsFromEnv(cmd *cobra.Command, environmentName string) error { + envConfigs := map[string]map[string]string{ + EnvMainnet: { + flags.FlagChainID: "osmosis-1", + flags.FlagNode: "https://rpc.osmosis.zone:443", + flags.FlagBroadcastMode: "block", + }, + EnvTestnet: { + flags.FlagChainID: "osmo-test-5", + flags.FlagNode: "https://rpc.testnet.osmosis.zone:443", + flags.FlagBroadcastMode: "block", + }, + EnvLocalnet: { + flags.FlagChainID: "localosmosis", + flags.FlagBroadcastMode: "block", + }, + } + + configs, ok := envConfigs[environmentName] + if !ok { + return nil + } + + for flag, value := range configs { + if err := runConfigCmd(cmd, []string{flag, value}); err != nil { + return err + } + } + return nil +} + +// changeEnvironment takes the given environment name and changes the .env file to reflect it. +func changeEnvironment(args []string) error { + newEnv := args[0] + + currentEnvironment := getHomeEnvironment() + fmt.Println("Current environment: ", currentEnvironment) + + if _, err := environmentNameToPath(newEnv); err != nil { + return err + } + + fmt.Println("New environment: ", newEnv) + + envMap := make(map[string]string) + envMap[EnvVariable] = newEnv + err := godotenv.Write(envMap, filepath.Join(app.DefaultNodeHome, ".env")) + if err != nil { + return err + } + + return nil +} + +// createHomeDirIfNotExist creates the home directory if it does not exist and writes a blank +// .env file. This is used for the first time setup of the osmosisd home directory. +func createHomeDirIfNotExist(homeDir string) error { + if _, err := os.Stat(homeDir); os.IsNotExist(err) { + err := os.MkdirAll(homeDir, 0755) + if err != nil { + return err + } + } + + envFilePath := filepath.Join(homeDir, ".env") + if _, err := os.Stat(envFilePath); os.IsNotExist(err) { + file, err := os.Create(envFilePath) + if err != nil { + return err + } + file.Close() + } + + return nil +} + +// changeEnvPriorToSetup changes the env file to reflect the desired environment the user wants to change to. +// If this is not called in NewRootCmd(), the environment change will happen **after** all relevant setup actions +// happen (e.g., the .env will be read in as the previous value in the setup and not the new value). +func changeEnvPriorToSetup(cmd *cobra.Command, initClientCtx *client.Context, args []string, homeDir string) error { + if cmd.Name() == "set-env" && len(args) == 1 { + err := createHomeDirIfNotExist(homeDir) + if err != nil { + return err + } + + err = changeEnvironment(args) + if err != nil { + return err + } + + homeEnvironment := getHomeEnvironment() + homeDir, err := environmentNameToPath(homeEnvironment) + if err != nil { + // Failed to convert home environment to home path, using default home + homeDir = app.DefaultNodeHome + } + *initClientCtx = initClientCtx.WithHomeDir(homeDir) } + return nil } diff --git a/cmd/osmosisd/cmd/root.go b/cmd/osmosisd/cmd/root.go index 01ba5a597ed..29d36d0f8e9 100644 --- a/cmd/osmosisd/cmd/root.go +++ b/cmd/osmosisd/cmd/root.go @@ -287,6 +287,12 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) { Use: "osmosisd", Short: "Start osmosis app", PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + // If not calling the set-env command, this is a no-op. + err := changeEnvPriorToSetup(cmd, &initClientCtx, args, homeDir) + if err != nil { + return err + } + initClientCtx, err := client.ReadPersistentCommandFlags(initClientCtx, cmd.Flags()) if err != nil { return err @@ -391,8 +397,9 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) { func getHomeEnvironment() string { envPath := filepath.Join(osmosis.DefaultNodeHome, ".env") - // Use default node home if can't get environment - err := godotenv.Load(envPath) + // Use default node home if can't get environment. + // Overload must be used here in the event that the .env gets updated. + err := godotenv.Overload(envPath) if err != nil { // Failed to load, using default home directory return EnvMainnet diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 79a2bca1e96..f628eaddf2b 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -3,7 +3,6 @@ package e2e import ( "encoding/json" "fmt" - "github.com/cosmos/cosmos-sdk/types/address" "os" "path/filepath" "strconv" @@ -12,6 +11,8 @@ import ( "testing" "time" + "github.com/cosmos/cosmos-sdk/types/address" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/iancoleman/orderedmap" From 18f57bd1fb340099747230880c3f5acc1a25c5fc Mon Sep 17 00:00:00 2001 From: devbot-wizard <141283918+devbot-wizard@users.noreply.github.com> Date: Tue, 8 Aug 2023 23:28:13 +0000 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1ba7a8b0ac..e47c1183810 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#5890](https://github.com/osmosis-labs/osmosis/pull/5890) feat: CreateCLPool & LinkCFMMtoCL pool into one gov-prop * [#5964](https://github.com/osmosis-labs/osmosis/pull/5964) fix e2e test concurrency bugs * [#5948] (https://github.com/osmosis-labs/osmosis/pull/5948) Parameterizing Pool Type Information in Protorev +* [#6001](https://github.com/osmosis-labs/osmosis/pull/6001) feat: improve set-env CLI cmd ### Minor improvements & Bug Fixes From fe619d1f396bc29eb9c1855939640fbf6b219b7d Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Tue, 8 Aug 2023 20:40:58 -0500 Subject: [PATCH 3/3] add optional chain id to localnet --- cmd/osmosisd/cmd/change_environment.go | 34 ++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/cmd/osmosisd/cmd/change_environment.go b/cmd/osmosisd/cmd/change_environment.go index 7e37fead924..6fa28173ebf 100644 --- a/cmd/osmosisd/cmd/change_environment.go +++ b/cmd/osmosisd/cmd/change_environment.go @@ -1,6 +1,7 @@ package cmd import ( + "errors" "fmt" "os" "path/filepath" @@ -29,17 +30,21 @@ func ChangeEnvironmentCmd() *cobra.Command { Example: osmosisd set-env mainnet osmosisd set-env testnet - osmosisd set-env localnet + osmosisd set-env localnet [optional-chain-id] osmosisd set-env $HOME/.custom-dir `, - Args: cobra.ExactArgs(1), + Args: customArgs, RunE: func(cmd *cobra.Command, args []string) error { // Note: If we are calling this method, the environment file has already been set in // NewRootCmd() when creating the rootCmd. We do this because order of operations // dictates this as a requirement. If we changed the env file here, the osmosis // daemon would not initialize the folder we are intending to set to. newEnv := args[0] - return clientSettingsFromEnv(cmd, newEnv) + chainId := "" + if len(args) > 1 { + chainId = args[1] + } + return clientSettingsFromEnv(cmd, newEnv, chainId) }, } return cmd @@ -101,7 +106,7 @@ func environmentNameToPath(environmentName string) (string, error) { // clientSettingsFromEnv takes the env name (mainnet, testnet, localnet, etc) and sets the // client.toml settings to commonly used values for that environment. -func clientSettingsFromEnv(cmd *cobra.Command, environmentName string) error { +func clientSettingsFromEnv(cmd *cobra.Command, environmentName, chainId string) error { envConfigs := map[string]map[string]string{ EnvMainnet: { flags.FlagChainID: "osmosis-1", @@ -124,6 +129,11 @@ func clientSettingsFromEnv(cmd *cobra.Command, environmentName string) error { return nil } + // Update the ChainID if environmentName is EnvLocalnet and chainId is provided + if environmentName == EnvLocalnet && chainId != "" { + configs[flags.FlagChainID] = chainId + } + for flag, value := range configs { if err := runConfigCmd(cmd, []string{flag, value}); err != nil { return err @@ -181,7 +191,7 @@ func createHomeDirIfNotExist(homeDir string) error { // If this is not called in NewRootCmd(), the environment change will happen **after** all relevant setup actions // happen (e.g., the .env will be read in as the previous value in the setup and not the new value). func changeEnvPriorToSetup(cmd *cobra.Command, initClientCtx *client.Context, args []string, homeDir string) error { - if cmd.Name() == "set-env" && len(args) == 1 { + if cmd.Name() == "set-env" { err := createHomeDirIfNotExist(homeDir) if err != nil { return err @@ -202,3 +212,17 @@ func changeEnvPriorToSetup(cmd *cobra.Command, initClientCtx *client.Context, ar } return nil } + +// customArgs accepts one arg, but if the first arg is "localnet", then it accepts two args. +func customArgs(cmd *cobra.Command, args []string) error { + if len(args) < 1 || len(args) > 2 { + return errors.New("set-env requires 1 or 2 arguments") + } + if args[0] == "localnet" { + return nil + } + if len(args) == 2 { + return errors.New("only 'set-env localnet' accepts a second argument") + } + return nil +}