/// <inheritdoc/> public override void Run(CommandLine commandLine) { HiveProxy hiveProxy; if (commandLine.HasHelpOption || commandLine.Arguments.Length == 0) { Console.WriteLine(usage); Program.Exit(0); } Console.Error.WriteLine(); var hiveLogin = Program.HiveLogin; var login = HiveHelper.SplitLogin(commandLine.Arguments[0]); if (!login.IsOK) { Console.Error.WriteLine($"*** ERROR: Invalid username/hive [{commandLine.Arguments[0]}]. Expected something like: USER@HIVE"); Program.Exit(1); } // Check whether we're already logged into the hive. var username = login.Username; var hiveName = login.HiveName; if (hiveLogin != null && string.Equals(hiveLogin.HiveName, hiveName, StringComparison.OrdinalIgnoreCase) && string.Equals(hiveLogin.Username, username, StringComparison.OrdinalIgnoreCase)) { // Ensure that the client is compatible with the hive. try { HiveHelper.ValidateClientVersion(hiveLogin, Program.Version); } catch (VersionException e) { HiveHelper.VpnClose(null); CurrentHiveLogin.Delete(); Console.Error.WriteLine($"*** ERROR: {e.Message}"); Program.Exit(0); } // Ensure that the hive's certificates, hostnames,... are properly initialized. HiveHelper.OpenHive(hiveLogin); Console.Error.WriteLine($"*** You are already logged into [{Program.HiveLogin.Username}@{Program.HiveLogin.HiveName}]."); Program.Exit(0); } // Logout of the current hive. if (hiveLogin != null) { Console.Error.WriteLine($"Logging out of [{Program.HiveLogin.Username}@{Program.HiveLogin.HiveName}]."); CurrentHiveLogin.Delete(); } // We're passing NULL to close all hive VPN connections to ensure that // we're only connected to one at a time. It's very possible for a operator // to have to manage multiple disconnnected hives that share the same // IP address space. HiveHelper.VpnClose(null); // Fetch the new hive login. var hiveLoginPath = Program.GetHiveLoginPath(username, hiveName); if (!File.Exists(hiveLoginPath)) { Console.Error.WriteLine($"*** ERROR: Cannot find login [{username}@{hiveName}]."); Program.Exit(1); } hiveLogin = NeonHelper.JsonDeserialize <HiveLogin>(File.ReadAllText(hiveLoginPath)); // Determine whether we're going to use the VPN. var useVpn = false; var showVpn = commandLine.HasOption("--show-vpn"); if (hiveLogin.Definition.Hosting.IsOnPremiseProvider) { if (hiveLogin.Definition.Vpn.Enabled) { if (!commandLine.HasOption("--no-vpn")) { if (!hiveLogin.Definition.Vpn.Enabled) { Console.Error.WriteLine($"*** ERROR: Hive [{hiveLogin.HiveName}] was not provisioned with a VPN."); Program.Exit(1); } useVpn = true; } else { useVpn = false; Console.Error.WriteLine("Using the local network (not the VPN)"); } } else { useVpn = false; } } else { useVpn = true; // Always TRUE for cloud environments. } // Connect the VPN if enabled. if (useVpn) { HiveHelper.VpnOpen(hiveLogin, onStatus: message => Console.Error.WriteLine($"{message}"), onError: message => Console.Error.WriteLine($"*** ERROR {message}"), show: showVpn); } // Verify the credentials by logging into a manager node. Console.Error.WriteLine("Authenticating..."); hiveProxy = new HiveProxy(hiveLogin, (nodeName, publicAddress, privateAddress, append) => { return(new SshProxy <NodeDefinition>(nodeName, publicAddress, privateAddress, hiveLogin.GetSshCredentials(), TextWriter.Null)); }); var viaVpn = useVpn ? $" (via VPN)" : string.Empty; try { hiveProxy.GetReachableManager().Connect(); var currentLogin = new CurrentHiveLogin() { Login = hiveLogin.LoginName, ViaVpn = useVpn }; currentLogin.Save(); // Call GetLogin() with the client version so that the current hive // definition will be downloaded and so we'll also verify that the // current client is capable of managing the hive. try { HiveHelper.GetLogin(clientVersion: Program.Version); } catch (VersionException e) { HiveHelper.VpnClose(null); CurrentHiveLogin.Delete(); Console.Error.WriteLine($"*** ERROR: {e.Message}"); Program.Exit(1); } // Ensure that the hive's certificates, hostnames,... are properly initialized. HiveHelper.OpenHive(hiveLogin); Console.Error.WriteLine($"Logged into [{hiveLogin.LoginName}]{viaVpn}."); Console.Error.WriteLine(""); } catch (Exception e) { Console.Error.WriteLine($"*** ERROR: Hive login failed{viaVpn}: {NeonHelper.ExceptionError(e)}"); Console.Error.WriteLine(""); // Delete the current login because it failed. CurrentHiveLogin.Delete(); Program.Exit(1); } }