github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/cmd/puppeth/wizard_intro.go (about) 1 // Copyright 2017 The Spectrum Authors 2 // This file is part of Spectrum. 3 // 4 // Spectrum 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 // Spectrum 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 Spectrum. 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/SmartMeshFoundation/Spectrum/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 if w.network == "" { 63 fmt.Println("Please specify a network name to administer (no spaces, please)") 64 for { 65 w.network = w.readString() 66 if !strings.Contains(w.network, " ") { 67 fmt.Printf("\nSweet, you can set this via --network=%s next time!\n\n", w.network) 68 break 69 } 70 log.Error("I also like to live dangerously, still no spaces") 71 } 72 } 73 log.Info("Administering Ethereum network", "name", w.network) 74 75 // Load initial configurations and connect to all live servers 76 w.conf.path = filepath.Join(os.Getenv("HOME"), ".puppeth", w.network) 77 78 blob, err := ioutil.ReadFile(w.conf.path) 79 if err != nil { 80 log.Warn("No previous configurations found", "path", w.conf.path) 81 } else if err := json.Unmarshal(blob, &w.conf); err != nil { 82 log.Crit("Previous configuration corrupted", "path", w.conf.path, "err", err) 83 } else { 84 // Dial all previously known servers concurrently 85 var pend sync.WaitGroup 86 for server, pubkey := range w.conf.Servers { 87 pend.Add(1) 88 89 go func(server string, pubkey []byte) { 90 defer pend.Done() 91 92 log.Info("Dialing previously configured server", "server", server) 93 client, err := dial(server, pubkey) 94 if err != nil { 95 log.Error("Previous server unreachable", "server", server, "err", err) 96 } 97 w.lock.Lock() 98 w.servers[server] = client 99 w.lock.Unlock() 100 }(server, pubkey) 101 } 102 pend.Wait() 103 w.networkStats() 104 } 105 // Basics done, loop ad infinitum about what to do 106 for { 107 fmt.Println() 108 fmt.Println("What would you like to do? (default = stats)") 109 fmt.Println(" 1. Show network stats") 110 if w.conf.Genesis == nil { 111 fmt.Println(" 2. Configure new genesis") 112 } else { 113 fmt.Println(" 2. Manage existing genesis") 114 } 115 if len(w.servers) == 0 { 116 fmt.Println(" 3. Track new remote server") 117 } else { 118 fmt.Println(" 3. Manage tracked machines") 119 } 120 if len(w.services) == 0 { 121 fmt.Println(" 4. Deploy network components") 122 } else { 123 fmt.Println(" 4. Manage network components") 124 } 125 126 choice := w.read() 127 switch { 128 case choice == "" || choice == "1": 129 w.networkStats() 130 131 case choice == "2": 132 if w.conf.Genesis == nil { 133 w.makeGenesis() 134 } else { 135 w.manageGenesis() 136 } 137 case choice == "3": 138 if len(w.servers) == 0 { 139 if w.makeServer() != "" { 140 w.networkStats() 141 } 142 } else { 143 w.manageServers() 144 } 145 case choice == "4": 146 if len(w.services) == 0 { 147 w.deployComponent() 148 } else { 149 w.manageComponents() 150 } 151 152 default: 153 log.Error("That's not something I can do") 154 } 155 } 156 }