Heavy instancing work

Added InstanceRootCommand for blocking instance based commands if no
instance is chosen
CLI now prints the service version
Added service level CLI commands
Fixed Service.LockLoggingID
Added InstanceMetadata DataContract
Implemented Service.ListInstances
ExitCode is now set to int parent type
Fixed ConnectivityLevel flags
Optimized channel closing during instance switching
This commit is contained in:
Cyberboss
2017-10-31 16:55:01 -04:00
parent e6f44a10b3
commit 8db5ecb26d
18 changed files with 607 additions and 45 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ using TGServiceInterface.Components;
namespace TGCommandLine
{
class AdminCommand : RootCommand
class AdminCommand : InstanceRootCommand
{
public AdminCommand()
{
+1 -1
View File
@@ -6,7 +6,7 @@ using TGServiceInterface.Components;
namespace TGCommandLine
{
class BYONDCommand : RootCommand
class BYONDCommand : InstanceRootCommand
{
public BYONDCommand()
{
+2 -2
View File
@@ -5,7 +5,7 @@ using TGServiceInterface.Components;
namespace TGCommandLine
{
class IRCCommand : RootCommand
class IRCCommand : InstanceRootCommand
{
public IRCCommand()
{
@@ -17,7 +17,7 @@ namespace TGCommandLine
return "Manages the IRC bot";
}
}
class DiscordCommand : RootCommand
class DiscordCommand : InstanceRootCommand
{
public DiscordCommand()
{
+1 -1
View File
@@ -6,7 +6,7 @@ using TGServiceInterface.Components;
namespace TGCommandLine
{
class ConfigCommand : RootCommand
class ConfigCommand : InstanceRootCommand
{
public ConfigCommand()
{
+1 -1
View File
@@ -5,7 +5,7 @@ using TGServiceInterface.Components;
namespace TGCommandLine
{
class DDCommand : RootCommand
class DDCommand : InstanceRootCommand
{
public DDCommand()
{
+1 -1
View File
@@ -6,7 +6,7 @@ using TGServiceInterface.Components;
namespace TGCommandLine
{
class DMCommand : RootCommand
class DMCommand : InstanceRootCommand
{
public DMCommand()
{
+33
View File
@@ -0,0 +1,33 @@
using System.Collections.Generic;
using TGServiceInterface;
namespace TGCommandLine
{
abstract class InstanceRootCommand : RootCommand
{
public static Interface currentInterface;
public override ExitCode DoRun(IList<string> parameters)
{
if (currentInterface.InstanceName == null)
{
OutputProc("Missing instance!");
return ExitCode.BadCommand;
}
else
{
var res = currentInterface.ConnectToInstance();
if (!res.HasFlag(ConnectivityLevel.Connected))
{
OutputProc("Unable to connect to instance!");
return ExitCode.ConnectionError;
}
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
{
OutputProc("The current user is not authorized to use this instance!");
return ExitCode.ConnectionError;
}
}
return base.DoRun(parameters);
}
}
}
+50 -5
View File
@@ -9,7 +9,7 @@ namespace TGCommandLine
class Program
{
static bool interactive = false;
static bool interactive = false, saidSrvVersion = false;
static Interface currentInterface;
static Command.ExitCode RunCommandLine(IList<string> argsAsList)
{
@@ -83,6 +83,11 @@ namespace TGCommandLine
SentVMMWarning = true;
Console.WriteLine(error);
}
else if (interactive && !saidSrvVersion)
{
Console.WriteLine("Connectd to service version: " + currentInterface.GetService().Version());
saidSrvVersion = true;
}
try
{
@@ -97,7 +102,6 @@ namespace TGCommandLine
static void ReplaceInterface(Interface I)
{
if (!interactive)
I.SetBadCertificateHandler((message) =>
{
@@ -110,6 +114,8 @@ namespace TGCommandLine
I.SetBadCertificateHandler(BadCertificateInteractive);
currentInterface = I;
ConsoleCommand.Interface = I;
InstanceRootCommand.currentInterface = I;
saidSrvVersion = false;
}
public static string ReadLineSecure()
@@ -156,21 +162,60 @@ namespace TGCommandLine
return false;
}
/// <summary>
/// Tries to set <see cref="currentInterface"/>'s <see cref="ITGInstance"/> to <paramref name="instanceName"/>, outputting appropriate messages
/// </summary>
/// <param name="instanceName">The name of the <see cref="ITGInstance"/> to test</param>
/// <param name="silentSuccess">If <see langword="true"/>, does not output on success</param>
/// <returns><see langword="true"/> if a <see cref="ConnectivityLevel.Authenticated"/> was achieved with <see cref="Interface.ConnectToInstance(string)"/>, <see langword="false"/> otherwise</returns>
static bool CheckInstanceConnectivity(string instanceName, bool silentSuccess)
{
var res = currentInterface.ConnectToInstance(instanceName);
if (!res.HasFlag(ConnectivityLevel.Connected))
Console.WriteLine("Unable to connect to instance! Does it exist?");
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
Console.WriteLine("The current user is not authorized to use this instance!");
else
{
if(!silentSuccess)
Console.WriteLine("Successfully conected to instance!");
return true;
}
return false;
}
static int Main(string[] args)
{
ReplaceInterface(new Interface());
Command.OutputProcVar.Value = Console.WriteLine;
if (args.Length != 0)
return (int)RunCommandLine(new List<string>(args));
Console.WriteLine("Type 'remote' to connect to a remote service");
{
var argsAsList = new List<string>(args);
for (var I = 0; I < argsAsList.Count - 1; ++I)
if (argsAsList[I].ToLower() == "--instance")
{
if (!CheckInstanceConnectivity(args[I + 1], true))
return (int)Command.ExitCode.ConnectionError;
argsAsList.RemoveRange(I, 2);
break;
}
return (int)RunCommandLine(argsAsList);
}
//interactive mode
Console.WriteLine("Type 'instance' to connect to a server instance");
Console.WriteLine("Type 'remote' to connect to a remote service");
while (true)
{
Console.Write("Enter command: ");
var NextCommand = Console.ReadLine();
switch (NextCommand.ToLower())
{
case "instance":
Console.Write("Enter instance name: ");
CheckInstanceConnectivity(Console.ReadLine(), false);
break;
case "remote":
SentVMMWarning = false;
Console.Write("Enter server address: ");
+2
View File
@@ -12,6 +12,8 @@ namespace TGCommandLine
var tmp = new List<Command> { new UpdateCommand(), new TestmergeCommand(), new RepoCommand(), new BYONDCommand(), new DMCommand(), new DDCommand(), new ConfigCommand(), new IRCCommand(), new DiscordCommand(), new AutoUpdateCommand(), new SetAutoUpdateCommand() };
if (I.ConnectToInstance().HasFlag(ConnectivityLevel.Administrator))
tmp.Add(new AdminCommand());
if (I.ConnectionStatus().HasFlag(ConnectivityLevel.Administrator))
tmp.Add(new ServiceCommand());
Children = tmp.ToArray();
}
+433
View File
@@ -0,0 +1,433 @@
using System;
using System.Collections.Generic;
using TGServiceInterface;
namespace TGCommandLine
{
/// <summary>
/// Used for managing the <see cref="TGServiceInterface.Components.ITGSService"/>
/// </summary>
class ServiceCommand : RootCommand
{
/// <summary>
/// Construct a <see cref="ServiceCommand"/>
/// </summary>
public ServiceCommand()
{
Keyword = "service";
Children = new Command[] { new ServiceCreateInstanceCommand(), new ServiceDetachInstanceCommand(), new ServiceEnableInstanceCommand(), new ServiceImportInstanceCommand(), new ServiceListInstancesCommand(), new ServicePythonPathCommand(), new ServiceSetPythonPathCommand(), new ServiceSetRemoteAccessPortCommand(), new ServiceRemoteAccessPortCommand(), new ServiceDisableInstanceCommand(), new ServiceRenameInstanceCommand() };
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Manage service wide settings";
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.CreateInstance(string, string)"/>
/// </summary>
class ServiceCreateInstanceCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceCreateInstanceCommand"/>
/// </summary>
public ServiceCreateInstanceCommand()
{
Keyword = "create-instance";
RequiredParameters = 2;
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Creates a new instance at the given path";
}
/// <inheritdoc />
public override string GetArgumentString()
{
return "<name> <path>";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetService().CreateInstance(parameters[0], parameters[1]);
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.ListInstances"/>
/// </summary>
class ServiceListInstancesCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceListInstancesCommand"/>
/// </summary>
public ServiceListInstancesCommand()
{
Keyword = "list-instances";
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Lists all instances";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
foreach (var I in Interface.GetService().ListInstances())
OutputProc(String.Format("{0} ({1}):\t{2}{3}", I.Name, I.Path, I.Enabled ? "Online" : "Offline", I.Enabled ? String.Format(" ({0})", I.LoggingID) : ""));
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.DetachInstance(string)"/>
/// </summary>
class ServiceDetachInstanceCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceDetachInstanceCommand"/>
/// </summary>
public ServiceDetachInstanceCommand()
{
Keyword = "detach-instance";
RequiredParameters = 1;
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Detaches an instance";
}
/// <inheritdoc />
public override string GetArgumentString()
{
return "<name>";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetService().DetachInstance(parameters[0]);
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.ImportInstance(string)"/>
/// </summary>
class ServiceImportInstanceCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceImportInstanceCommand"/>
/// </summary>
public ServiceImportInstanceCommand()
{
Keyword = "import-instance";
RequiredParameters = 1;
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Imports an instance (Chat settings will be lost if they are from a different windows installation)";
}
/// <inheritdoc />
public override string GetArgumentString()
{
return "<path>";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetService().ImportInstance(parameters[0]);
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.PythonPath"/>
/// </summary>
class ServicePythonPathCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServicePythonPathCommand"/>
/// </summary>
public ServicePythonPathCommand()
{
Keyword = "python";
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Displays configured path the service uses for python";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetService().PythonPath();
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetPythonPath(string)"/>
/// </summary>
class ServiceSetPythonPathCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceSetPythonPathCommand"/>
/// </summary>
public ServiceSetPythonPathCommand()
{
Keyword = "set-python";
RequiredParameters = 1;
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Sets the path to the python installation";
}
/// <inheritdoc />
public override string GetArgumentString()
{
return "<path>";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
Interface.GetService().SetPythonPath(parameters[0]);
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetInstanceEnabled(string, bool)"/> with a <see langword="true"/> parameter
/// </summary>
class ServiceEnableInstanceCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceEnableInstanceCommand"/>
/// </summary>
public ServiceEnableInstanceCommand()
{
Keyword = "enable-instance";
RequiredParameters = 1;
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Enables the specified instance";
}
/// <inheritdoc />
public override string GetArgumentString()
{
return "<name>";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetService().SetInstanceEnabled(parameters[0], true);
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetInstanceEnabled(string, bool)"/> with a <see langword="false"/> parameter
/// </summary>
class ServiceDisableInstanceCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceDisableInstanceCommand"/>
/// </summary>
public ServiceDisableInstanceCommand()
{
Keyword = "disable-instance";
RequiredParameters = 1;
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Disables the specified instance";
}
/// <inheritdoc />
public override string GetArgumentString()
{
return "<name>";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetService().SetInstanceEnabled(parameters[0], false);
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.RemoteAccessPort"/>
/// </summary>
class ServiceRemoteAccessPortCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceRemoteAccessPortCommand"/>
/// </summary>
public ServiceRemoteAccessPortCommand()
{
Keyword = "port";
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Displays the service's remote access port";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
OutputProc(Interface.GetService().RemoteAccessPort().ToString());
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetRemoteAccessPort(ushort)"/>
/// </summary>
class ServiceSetRemoteAccessPortCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceSetRemoteAccessPortCommand"/>
/// </summary>
public ServiceSetRemoteAccessPortCommand()
{
Keyword = "set-port";
RequiredParameters = 1;
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Sets the service's remote access port";
}
/// <inheritdoc />
public override string GetArgumentString()
{
return "<port>";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
ushort port;
try
{
port = Convert.ToUInt16(parameters[0]);
}
catch
{
OutputProc("Invalid port number!");
return ExitCode.BadCommand;
}
var res = Interface.GetService().SetRemoteAccessPort(port);
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
OutputProc("Change will be applied after service restart");
return ExitCode.Normal;
}
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.RenameInstance(string, string)"/>
/// </summary>
class ServiceRenameInstanceCommand : ConsoleCommand
{
/// <summary>
/// Construct a <see cref="ServiceRenameInstanceCommand"/>
/// </summary>
public ServiceRenameInstanceCommand()
{
Keyword = "rename-instance";
RequiredParameters = 1;
}
/// <inheritdoc />
public override string GetHelpText()
{
return "Renames an instance. Will temporarily disable the instance if it is active";
}
/// <inheritdoc />
public override string GetArgumentString()
{
return "<name> <new_name>";
}
/// <inheritdoc />
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetService().RenameInstance(parameters[0], parameters[1]);
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
}
+2
View File
@@ -48,11 +48,13 @@
<Compile Include="DDCommands.cs" />
<Compile Include="DMCommands.cs" />
<Compile Include="ChatCommands.cs" />
<Compile Include="InstanceRootCommand.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RepoCommands.cs" />
<Compile Include="RootCommands.cs" />
<Compile Include="..\Version.cs" />
<Compile Include="ServiceCommands.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />