github.com/smartcontractkit/chainlink-testing-framework/libs@v0.0.0-20240227141906-ec710b4eb1a3/docker/test_env/cmd/internal/start_test_env_commands.go (about) 1 package internal 2 3 import ( 4 "fmt" 5 "io" 6 defaultlog "log" 7 "os" 8 "os/signal" 9 "strings" 10 "syscall" 11 12 "github.com/rs/zerolog" 13 "github.com/spf13/cobra" 14 flag "github.com/spf13/pflag" 15 "github.com/testcontainers/testcontainers-go" 16 17 "github.com/smartcontractkit/chainlink-testing-framework/libs/docker/test_env" 18 "github.com/smartcontractkit/chainlink-testing-framework/libs/logging" 19 ) 20 21 var StartTestEnvCmd = &cobra.Command{ 22 Use: "start-test-env", 23 Short: "Start local test environment", 24 } 25 26 var startPrivateChain = &cobra.Command{ 27 Use: "private-chain", 28 Short: "Private chain with 1 node", 29 RunE: startPrivateEthChainE, 30 } 31 32 const ( 33 Flag_ConsensusType = "consensus-type" 34 Flag_ConsensusLayer = "consensus-layer" 35 Flag_ExecutionLayer = "execution-layer" 36 Flag_WaitForFinalization = "wait-for-finalization" 37 Flag_ChainID = "chain-id" 38 Flag_ExecutionClientImage = "execution-layer-image" 39 Flag_ConsensucClientImage = "consensus-client-image" 40 Flag_ValidatorImage = "validator-image" 41 ) 42 43 func init() { 44 StartTestEnvCmd.AddCommand(startPrivateChain) 45 46 StartTestEnvCmd.PersistentFlags().StringP( 47 Flag_ConsensusType, 48 "t", 49 "pos", 50 "consensus type (pow or pos)", 51 ) 52 53 StartTestEnvCmd.PersistentFlags().StringP( 54 Flag_ConsensusLayer, 55 "l", 56 "prysm", 57 "consensus layer (prysm)", 58 ) 59 60 StartTestEnvCmd.PersistentFlags().StringP( 61 Flag_ExecutionLayer, 62 "e", 63 "geth", 64 "execution layer (geth, nethermind, besu or erigon)", 65 ) 66 67 StartTestEnvCmd.PersistentFlags().BoolP( 68 Flag_WaitForFinalization, 69 "w", 70 false, 71 "wait for finalization of at least 1 epoch (might take up to 5 mintues)", 72 ) 73 74 StartTestEnvCmd.PersistentFlags().IntP( 75 Flag_ChainID, 76 "c", 77 1337, 78 "chain id", 79 ) 80 81 StartTestEnvCmd.PersistentFlags().String( 82 Flag_ExecutionClientImage, 83 "", 84 "custom Docker image for execution layer client", 85 ) 86 87 StartTestEnvCmd.PersistentFlags().String( 88 Flag_ConsensucClientImage, 89 "", 90 "custom Docker image for consensus layer client", 91 ) 92 93 StartTestEnvCmd.PersistentFlags().String( 94 Flag_ValidatorImage, 95 "", 96 "custom Docker image for validator", 97 ) 98 99 // Set default log level for non-testcontainer code 100 zerolog.SetGlobalLevel(zerolog.InfoLevel) 101 102 // Discard testcontainers logs 103 testcontainers.Logger = defaultlog.New(io.Discard, "", defaultlog.LstdFlags) 104 } 105 106 func startPrivateEthChainE(cmd *cobra.Command, args []string) error { 107 log := logging.GetTestLogger(nil) 108 flags := cmd.Flags() 109 110 consensusType, err := flags.GetString(Flag_ConsensusType) 111 if err != nil { 112 return err 113 } 114 115 consensusType = strings.ToLower(consensusType) 116 117 if consensusType != "pos" && consensusType != "pow" { 118 return fmt.Errorf("invalid consensus type: %s. use 'pow' or 'pos'", consensusType) 119 } 120 121 consensusLayer, err := flags.GetString(Flag_ConsensusLayer) 122 if err != nil { 123 return err 124 } 125 126 consensusLayer = strings.ToLower(consensusLayer) 127 128 if consensusLayer != "" && consensusLayer != "prysm" { 129 return fmt.Errorf("invalid consensus layer: %s. use 'prysm'", consensusLayer) 130 } 131 132 if consensusLayer != "" && consensusType == "pow" { 133 log.Warn().Msg("consensus layer was set, but it has no sense for a PoW conensus. Ignoring it") 134 } 135 136 executionLayer, err := flags.GetString(Flag_ExecutionLayer) 137 if err != nil { 138 return err 139 } 140 141 executionLayer = strings.ToLower(executionLayer) 142 switch executionLayer { 143 case "geth", "nethermind", "besu", "erigon": 144 default: 145 return fmt.Errorf("invalid execution layer: %s. use 'geth', 'nethermind', 'besu' or 'erigon'", executionLayer) 146 } 147 148 waitForFinalization, err := flags.GetBool(Flag_WaitForFinalization) 149 if err != nil { 150 return err 151 } 152 153 chainId, err := flags.GetInt(Flag_ChainID) 154 if err != nil { 155 return err 156 } 157 158 consensusLayerToUse := test_env.ConsensusLayer(consensusLayer) 159 if consensusLayer != "" && consensusType == "pow" { 160 consensusLayerToUse = "" 161 } 162 163 customDockerImages, err := getCustomImages(flags) 164 if err != nil { 165 return err 166 } 167 168 builder := test_env.NewEthereumNetworkBuilder() 169 builder = *builder.WithConsensusType(test_env.ConsensusType(consensusType)). 170 WithConsensusLayer(consensusLayerToUse). 171 WithExecutionLayer(test_env.ExecutionLayer(executionLayer)). 172 WithEthereumChainConfig(test_env.EthereumChainConfig{ 173 ValidatorCount: 8, 174 SlotsPerEpoch: 2, 175 SecondsPerSlot: 6, 176 ChainID: chainId, 177 }) 178 179 if waitForFinalization { 180 builder = *builder.WithWaitingForFinalization() 181 } 182 183 if len(customDockerImages) > 0 { 184 builder = *builder.WithCustomDockerImages(customDockerImages) 185 } 186 187 cfg, err := builder. 188 Build() 189 190 log.Info().Str("chain", cfg.Describe()).Msg("Starting private chain") 191 192 if err != nil { 193 return err 194 } 195 196 _, eth2, err := cfg.Start() 197 198 if err != nil { 199 return err 200 } 201 log.Info().Msg("---------- Private chain is ready ----------") 202 log.Info().Msgf("Public RPC WS URLs: %v", eth2.PublicWsUrls()) 203 log.Info().Msgf("Public RPC HTTP URLs: %v", eth2.PublicHttpUrls()) 204 205 err = cfg.Save() 206 if err != nil { 207 return err 208 } 209 210 handleExitSignal() 211 212 return nil 213 } 214 215 func handleExitSignal() { 216 // Create a channel to receive exit signals 217 exitChan := make(chan os.Signal, 1) 218 signal.Notify(exitChan, os.Interrupt, syscall.SIGTERM) 219 220 log := logging.GetTestLogger(nil) 221 log.Info().Msg("Press Ctrl+C to destroy the test environment") 222 223 // Block until an exit signal is received 224 <-exitChan 225 } 226 227 func getCustomImages(flags *flag.FlagSet) (map[test_env.ContainerType]string, error) { 228 customImages := make(map[test_env.ContainerType]string) 229 executionClientImage, err := flags.GetString(Flag_ExecutionClientImage) 230 if err != nil { 231 return nil, err 232 } 233 234 if executionClientImage != "" { 235 customImages[test_env.ContainerType_Besu] = executionClientImage 236 customImages[test_env.ContainerType_Erigon] = executionClientImage 237 customImages[test_env.ContainerType_Geth] = executionClientImage 238 customImages[test_env.ContainerType_Nethermind] = executionClientImage 239 } 240 241 consensusClientImage, err := flags.GetString(Flag_ConsensucClientImage) 242 if err != nil { 243 return nil, err 244 } 245 246 if consensusClientImage != "" { 247 customImages[test_env.ContainerType_PrysmBeacon] = consensusClientImage 248 } 249 250 validatorImage, err := flags.GetString(Flag_ValidatorImage) 251 if err != nil { 252 return nil, err 253 } 254 255 if validatorImage != "" { 256 customImages[test_env.ContainerType_PrysmVal] = validatorImage 257 } 258 259 return customImages, nil 260 }