github.com/MetalBlockchain/metalgo@v1.11.9/tests/fixture/tmpnet/cmd/main.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package main 5 6 import ( 7 "context" 8 "errors" 9 "fmt" 10 "io/fs" 11 "os" 12 "path/filepath" 13 "time" 14 15 "github.com/spf13/cobra" 16 17 "github.com/MetalBlockchain/metalgo/tests/fixture/tmpnet" 18 "github.com/MetalBlockchain/metalgo/version" 19 ) 20 21 const cliVersion = "0.0.1" 22 23 var ( 24 errAvalancheGoRequired = fmt.Errorf("--metalgo-path or %s are required", tmpnet.AvalancheGoPathEnvName) 25 errNetworkDirRequired = fmt.Errorf("--network-dir or %s are required", tmpnet.NetworkDirEnvName) 26 ) 27 28 func main() { 29 var networkDir string 30 rootCmd := &cobra.Command{ 31 Use: "tmpnetctl", 32 Short: "tmpnetctl commands", 33 } 34 rootCmd.PersistentFlags().StringVar(&networkDir, "network-dir", os.Getenv(tmpnet.NetworkDirEnvName), "The path to the configuration directory of a temporary network") 35 36 versionCmd := &cobra.Command{ 37 Use: "version", 38 Short: "Print version details", 39 RunE: func(*cobra.Command, []string) error { 40 msg := cliVersion 41 if len(version.GitCommit) > 0 { 42 msg += ", commit=" + version.GitCommit 43 } 44 fmt.Fprintf(os.Stdout, msg+"\n") 45 return nil 46 }, 47 } 48 rootCmd.AddCommand(versionCmd) 49 50 var ( 51 rootDir string 52 networkOwner string 53 avalancheGoPath string 54 pluginDir string 55 nodeCount uint8 56 ) 57 startNetworkCmd := &cobra.Command{ 58 Use: "start-network", 59 Short: "Start a new temporary network", 60 RunE: func(*cobra.Command, []string) error { 61 if len(avalancheGoPath) == 0 { 62 return errAvalancheGoRequired 63 } 64 65 // Root dir will be defaulted on start if not provided 66 67 network := &tmpnet.Network{ 68 Owner: networkOwner, 69 Nodes: tmpnet.NewNodesOrPanic(int(nodeCount)), 70 } 71 72 // Extreme upper bound, should never take this long 73 networkStartTimeout := 2 * time.Minute 74 75 ctx, cancel := context.WithTimeout(context.Background(), networkStartTimeout) 76 defer cancel() 77 err := tmpnet.BootstrapNewNetwork( 78 ctx, 79 os.Stdout, 80 network, 81 rootDir, 82 avalancheGoPath, 83 pluginDir, 84 ) 85 if err != nil { 86 return err 87 } 88 89 // Symlink the new network to the 'latest' network to simplify usage 90 networkRootDir := filepath.Dir(network.Dir) 91 networkDirName := filepath.Base(network.Dir) 92 latestSymlinkPath := filepath.Join(networkRootDir, "latest") 93 if err := os.Remove(latestSymlinkPath); err != nil && !errors.Is(err, fs.ErrNotExist) { 94 return err 95 } 96 if err := os.Symlink(networkDirName, latestSymlinkPath); err != nil { 97 return err 98 } 99 100 fmt.Fprintln(os.Stdout, "\nConfigure tmpnetctl to target this network by default with one of the following statements:") 101 fmt.Fprintf(os.Stdout, " - source %s\n", network.EnvFilePath()) 102 fmt.Fprintf(os.Stdout, " - %s\n", network.EnvFileContents()) 103 fmt.Fprintf(os.Stdout, " - export %s=%s\n", tmpnet.NetworkDirEnvName, latestSymlinkPath) 104 105 return nil 106 }, 107 } 108 startNetworkCmd.PersistentFlags().StringVar(&rootDir, "root-dir", os.Getenv(tmpnet.RootDirEnvName), "The path to the root directory for temporary networks") 109 startNetworkCmd.PersistentFlags().StringVar(&avalancheGoPath, "metalgo-path", os.Getenv(tmpnet.AvalancheGoPathEnvName), "The path to a metalgo binary") 110 startNetworkCmd.PersistentFlags().StringVar(&pluginDir, "plugin-dir", os.ExpandEnv("$HOME/.avalanchego/plugins"), "[optional] the dir containing VM plugins") 111 startNetworkCmd.PersistentFlags().Uint8Var(&nodeCount, "node-count", tmpnet.DefaultNodeCount, "Number of nodes the network should initially consist of") 112 startNetworkCmd.PersistentFlags().StringVar(&networkOwner, "network-owner", "", "The string identifying the intended owner of the network") 113 rootCmd.AddCommand(startNetworkCmd) 114 115 stopNetworkCmd := &cobra.Command{ 116 Use: "stop-network", 117 Short: "Stop a temporary network", 118 RunE: func(*cobra.Command, []string) error { 119 if len(networkDir) == 0 { 120 return errNetworkDirRequired 121 } 122 ctx, cancel := context.WithTimeout(context.Background(), tmpnet.DefaultNetworkTimeout) 123 defer cancel() 124 if err := tmpnet.StopNetwork(ctx, networkDir); err != nil { 125 return err 126 } 127 fmt.Fprintf(os.Stdout, "Stopped network configured at: %s\n", networkDir) 128 return nil 129 }, 130 } 131 rootCmd.AddCommand(stopNetworkCmd) 132 133 restartNetworkCmd := &cobra.Command{ 134 Use: "restart-network", 135 Short: "Restart a temporary network", 136 RunE: func(*cobra.Command, []string) error { 137 if len(networkDir) == 0 { 138 return errNetworkDirRequired 139 } 140 ctx, cancel := context.WithTimeout(context.Background(), tmpnet.DefaultNetworkTimeout) 141 defer cancel() 142 return tmpnet.RestartNetwork(ctx, os.Stdout, networkDir) 143 }, 144 } 145 rootCmd.AddCommand(restartNetworkCmd) 146 147 if err := rootCmd.Execute(); err != nil { 148 fmt.Fprintf(os.Stderr, "tmpnetctl failed: %v\n", err) 149 os.Exit(1) 150 } 151 os.Exit(0) 152 }