github.hscsec.cn/scroll-tech/go-ethereum@v1.9.7/cmd/puppeth/wizard_intro.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "bufio" 21 "encoding/json" 22 "fmt" 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "strings" 27 "sync" 28 29 "github.com/ethereum/go-ethereum/log" 30 ) 31 32 // makeWizard creates and returns a new puppeth wizard. 33 func makeWizard(network string) *wizard { 34 return &wizard{ 35 network: network, 36 conf: config{ 37 Servers: make(map[string][]byte), 38 }, 39 servers: make(map[string]*sshClient), 40 services: make(map[string][]string), 41 in: bufio.NewReader(os.Stdin), 42 } 43 } 44 45 // run displays some useful infos to the user, starting on the journey of 46 // setting up a new or managing an existing Ethereum private network. 47 func (w *wizard) run() { 48 fmt.Println("+-----------------------------------------------------------+") 49 fmt.Println("| Welcome to puppeth, your Ethereum private network manager |") 50 fmt.Println("| |") 51 fmt.Println("| This tool lets you create a new Ethereum network down to |") 52 fmt.Println("| the genesis block, bootnodes, miners and ethstats servers |") 53 fmt.Println("| without the hassle that it would normally entail. |") 54 fmt.Println("| |") 55 fmt.Println("| Puppeth uses SSH to dial in to remote servers, and builds |") 56 fmt.Println("| its network components out of Docker containers using the |") 57 fmt.Println("| docker-compose toolset. |") 58 fmt.Println("+-----------------------------------------------------------+") 59 fmt.Println() 60 61 // Make sure we have a good network name to work with fmt.Println() 62 // Docker accepts hyphens in image names, but doesn't like it for container names 63 if w.network == "" { 64 fmt.Println("Please specify a network name to administer (no spaces, hyphens or capital letters please)") 65 for { 66 w.network = w.readString() 67 if !strings.Contains(w.network, " ") && !strings.Contains(w.network, "-") && strings.ToLower(w.network) == w.network { 68 fmt.Printf("\nSweet, you can set this via --network=%s next time!\n\n", w.network) 69 break 70 } 71 log.Error("I also like to live dangerously, still no spaces, hyphens or capital letters") 72 } 73 } 74 log.Info("Administering Ethereum network", "name", w.network) 75 76 // Load initial configurations and connect to all live servers 77 w.conf.path = filepath.Join(os.Getenv("HOME"), ".puppeth", w.network) 78 79 blob, err := ioutil.ReadFile(w.conf.path) 80 if err != nil { 81 log.Warn("No previous configurations found", "path", w.conf.path) 82 } else if err := json.Unmarshal(blob, &w.conf); err != nil { 83 log.Crit("Previous configuration corrupted", "path", w.conf.path, "err", err) 84 } else { 85 // Dial all previously known servers concurrently 86 var pend sync.WaitGroup 87 for server, pubkey := range w.conf.Servers { 88 pend.Add(1) 89 90 go func(server string, pubkey []byte) { 91 defer pend.Done() 92 93 log.Info("Dialing previously configured server", "server", server) 94 client, err := dial(server, pubkey) 95 if err != nil { 96 log.Error("Previous server unreachable", "server", server, "err", err) 97 } 98 w.lock.Lock() 99 w.servers[server] = client 100 w.lock.Unlock() 101 }(server, pubkey) 102 } 103 pend.Wait() 104 w.networkStats() 105 } 106 // Basics done, loop ad infinitum about what to do 107 for { 108 fmt.Println() 109 fmt.Println("What would you like to do? (default = stats)") 110 fmt.Println(" 1. Show network stats") 111 if w.conf.Genesis == nil { 112 fmt.Println(" 2. Configure new genesis") 113 } else { 114 fmt.Println(" 2. Manage existing genesis") 115 } 116 if len(w.servers) == 0 { 117 fmt.Println(" 3. Track new remote server") 118 } else { 119 fmt.Println(" 3. Manage tracked machines") 120 } 121 if len(w.services) == 0 { 122 fmt.Println(" 4. Deploy network components") 123 } else { 124 fmt.Println(" 4. Manage network components") 125 } 126 127 choice := w.read() 128 switch { 129 case choice == "" || choice == "1": 130 w.networkStats() 131 132 case choice == "2": 133 if w.conf.Genesis == nil { 134 fmt.Println() 135 fmt.Println("What would you like to do? (default = create)") 136 fmt.Println(" 1. Create new genesis from scratch") 137 fmt.Println(" 2. Import already existing genesis") 138 139 choice := w.read() 140 switch { 141 case choice == "" || choice == "1": 142 w.makeGenesis() 143 case choice == "2": 144 w.importGenesis() 145 default: 146 log.Error("That's not something I can do") 147 } 148 } else { 149 w.manageGenesis() 150 } 151 case choice == "3": 152 if len(w.servers) == 0 { 153 if w.makeServer() != "" { 154 w.networkStats() 155 } 156 } else { 157 w.manageServers() 158 } 159 case choice == "4": 160 if len(w.services) == 0 { 161 w.deployComponent() 162 } else { 163 w.manageComponents() 164 } 165 default: 166 log.Error("That's not something I can do") 167 } 168 } 169 }