wizard_network.go 6.0 KB

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