github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/cmd/puppeth/wizard_network.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 "fmt" 21 "strings" 22 23 "github.com/zhiqiangxu/go-ethereum/log" 24 ) 25 26 // manageServers displays a list of servers the user can disconnect from, and an 27 // option to connect to new servers. 28 func (w *wizard) manageServers() { 29 // List all the servers we can disconnect, along with an entry to connect a new one 30 fmt.Println() 31 32 servers := w.conf.servers() 33 for i, server := range servers { 34 fmt.Printf(" %d. Disconnect %s\n", i+1, server) 35 } 36 fmt.Printf(" %d. Connect another server\n", len(w.conf.Servers)+1) 37 38 choice := w.readInt() 39 if choice < 0 || choice > len(w.conf.Servers)+1 { 40 log.Error("Invalid server choice, aborting") 41 return 42 } 43 // If the user selected an existing server, drop it 44 if choice <= len(w.conf.Servers) { 45 server := servers[choice-1] 46 client := w.servers[server] 47 48 delete(w.servers, server) 49 if client != nil { 50 client.Close() 51 } 52 delete(w.conf.Servers, server) 53 w.conf.flush() 54 55 log.Info("Disconnected existing server", "server", server) 56 w.networkStats() 57 return 58 } 59 // If the user requested connecting a new server, do it 60 if w.makeServer() != "" { 61 w.networkStats() 62 } 63 } 64 65 // makeServer reads a single line from stdin and interprets it as 66 // username:identity@hostname to connect to. It tries to establish a 67 // new SSH session and also executing some baseline validations. 68 // 69 // If connection succeeds, the server is added to the wizards configs! 70 func (w *wizard) makeServer() string { 71 fmt.Println() 72 fmt.Println("What is the remote server's address ([username[:identity]@]hostname[:port])?") 73 74 // Read and dial the server to ensure docker is present 75 input := w.readString() 76 77 client, err := dial(input, nil) 78 if err != nil { 79 log.Error("Server not ready for puppeth", "err", err) 80 return "" 81 } 82 // All checks passed, start tracking the server 83 w.servers[input] = client 84 w.conf.Servers[input] = client.pubkey 85 w.conf.flush() 86 87 return input 88 } 89 90 // selectServer lists the user all the currently known servers to choose from, 91 // also granting the option to add a new one. 92 func (w *wizard) selectServer() string { 93 // List the available server to the user and wait for a choice 94 fmt.Println() 95 fmt.Println("Which server do you want to interact with?") 96 97 servers := w.conf.servers() 98 for i, server := range servers { 99 fmt.Printf(" %d. %s\n", i+1, server) 100 } 101 fmt.Printf(" %d. Connect another server\n", len(w.conf.Servers)+1) 102 103 choice := w.readInt() 104 if choice < 0 || choice > len(w.conf.Servers)+1 { 105 log.Error("Invalid server choice, aborting") 106 return "" 107 } 108 // If the user requested connecting to a new server, go for it 109 if choice <= len(w.conf.Servers) { 110 return servers[choice-1] 111 } 112 return w.makeServer() 113 } 114 115 // manageComponents displays a list of network components the user can tear down 116 // and an option 117 func (w *wizard) manageComponents() { 118 // List all the components we can tear down, along with an entry to deploy a new one 119 fmt.Println() 120 121 var serviceHosts, serviceNames []string 122 for server, services := range w.services { 123 for _, service := range services { 124 serviceHosts = append(serviceHosts, server) 125 serviceNames = append(serviceNames, service) 126 127 fmt.Printf(" %d. Tear down %s on %s\n", len(serviceHosts), strings.Title(service), server) 128 } 129 } 130 fmt.Printf(" %d. Deploy new network component\n", len(serviceHosts)+1) 131 132 choice := w.readInt() 133 if choice < 0 || choice > len(serviceHosts)+1 { 134 log.Error("Invalid component choice, aborting") 135 return 136 } 137 // If the user selected an existing service, destroy it 138 if choice <= len(serviceHosts) { 139 // Figure out the service to destroy and execute it 140 service := serviceNames[choice-1] 141 server := serviceHosts[choice-1] 142 client := w.servers[server] 143 144 if out, err := tearDown(client, w.network, service, true); err != nil { 145 log.Error("Failed to tear down component", "err", err) 146 if len(out) > 0 { 147 fmt.Printf("%s\n", out) 148 } 149 return 150 } 151 // Clean up any references to it from out state 152 services := w.services[server] 153 for i, name := range services { 154 if name == service { 155 w.services[server] = append(services[:i], services[i+1:]...) 156 if len(w.services[server]) == 0 { 157 delete(w.services, server) 158 } 159 } 160 } 161 log.Info("Torn down existing component", "server", server, "service", service) 162 return 163 } 164 // If the user requested deploying a new component, do it 165 w.deployComponent() 166 } 167 168 // deployComponent displays a list of network components the user can deploy and 169 // guides through the process. 170 func (w *wizard) deployComponent() { 171 // Print all the things we can deploy and wait or user choice 172 fmt.Println() 173 fmt.Println("What would you like to deploy? (recommended order)") 174 fmt.Println(" 1. Ethstats - Network monitoring tool") 175 fmt.Println(" 2. Bootnode - Entry point of the network") 176 fmt.Println(" 3. Sealer - Full node minting new blocks") 177 fmt.Println(" 4. Explorer - Chain analysis webservice") 178 fmt.Println(" 5. Wallet - Browser wallet for quick sends") 179 fmt.Println(" 6. Faucet - Crypto faucet to give away funds") 180 fmt.Println(" 7. Dashboard - Website listing above web-services") 181 182 switch w.read() { 183 case "1": 184 w.deployEthstats() 185 case "2": 186 w.deployNode(true) 187 case "3": 188 w.deployNode(false) 189 case "4": 190 w.deployExplorer() 191 case "5": 192 w.deployWallet() 193 case "6": 194 w.deployFaucet() 195 case "7": 196 w.deployDashboard() 197 default: 198 log.Error("That's not something I can do") 199 } 200 }