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