diff --git a/Playground/CruiseControl.Command/Command.cs b/Playground/CruiseControl.Command/Command.cs new file mode 100644 index 000000000..0cb78b6b6 --- /dev/null +++ b/Playground/CruiseControl.Command/Command.cs @@ -0,0 +1,15 @@ +namespace CruiseControl.Command +{ + public class Command + { + #region Public properties + #region Name + public string Name { get; set; } + #endregion + + #region Arguments + public string[] Arguments { get; set; } + #endregion + #endregion + } +} diff --git a/Playground/CruiseControl.Command/CruiseControl.Command.csproj b/Playground/CruiseControl.Command/CruiseControl.Command.csproj index a90aa42b3..258bae7bb 100644 --- a/Playground/CruiseControl.Command/CruiseControl.Command.csproj +++ b/Playground/CruiseControl.Command/CruiseControl.Command.csproj @@ -43,6 +43,7 @@ + diff --git a/Playground/CruiseControl.Command/Program.cs b/Playground/CruiseControl.Command/Program.cs index dbfffb59c..1330c60e4 100644 --- a/Playground/CruiseControl.Command/Program.cs +++ b/Playground/CruiseControl.Command/Program.cs @@ -1,5 +1,8 @@ namespace CruiseControl.Command { + using System; + using System.Diagnostics; + using System.Linq; using CruiseControl.Common; class Program @@ -7,7 +10,113 @@ class Program static void Main(string[] args) { var connection = new ServerConnection(args[0]); - connection.Ping(); + var exit = false; + WriteToConsole(ConsoleColor.White, "CruiseControl.NET: Interactive Console"); + WriteToConsole(ConsoleColor.White, new string('=', 40)); + WriteToConsole(ConsoleColor.Yellow, "Retrieving server name..."); + var fullUrn = connection.RetrieveServerName(); + WriteToConsole(ConsoleColor.Yellow, "...server name is '{0}'", fullUrn); + var shortUrn = fullUrn.Substring(10); + while (!exit) + { + Console.Write(shortUrn + ">"); + var command = ReadFromConsole(); + switch (command.Name) + { + case "exit": + exit = true; + break; + + case "ping": + RunPingCommand(connection); + break; + + case "query": + RunQueryCommand(connection, fullUrn); + break; + + case "invoke": + RunInvokeCommand(connection, fullUrn, command.Arguments); + break; + } + } + } + + private static Command ReadFromConsole() + { + var input = Console.ReadLine(); + var parts = input.Split(' '); + var command = new Command(); + if (parts.Length > 0) + { + command.Name = parts[0].ToLowerInvariant(); + command.Arguments = parts.Skip(1).ToArray(); + } + + return command; + } + + private static void WriteToConsole(ConsoleColor colour, string message, params object[] args) + { + var oldColour = Console.ForegroundColor; + try + { + Console.ForegroundColor = colour; + Console.WriteLine(message, args); + } + finally + { + Console.ForegroundColor = oldColour; + } + } + + private static void RunPingCommand(ServerConnection connection) + { + WriteToConsole(ConsoleColor.Yellow, "Sending ping..."); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + var result = connection.Ping(); + stopwatch.Stop(); + if (result) + { + WriteToConsole(ConsoleColor.Yellow, "...ping received in {0}ms", stopwatch.ElapsedMilliseconds); + } + else + { + WriteToConsole(ConsoleColor.Red, "...ping failed!", stopwatch.ElapsedMilliseconds); + } + } + + private static void RunQueryCommand(ServerConnection connection, string fullUrn) + { + WriteToConsole(ConsoleColor.Yellow, "Querying '{0}'...", fullUrn); + try + { + var result = connection.Query(fullUrn); + WriteToConsole(ConsoleColor.Yellow, "...{0} action(s) retrieved", result.Length); + foreach (var action in result) + { + WriteToConsole(ConsoleColor.White, "\t{0}", action.Name); + } + } + catch (Exception error) + { + WriteToConsole(ConsoleColor.Red, "...failed: " + error.Message); + } + } + + private static void RunInvokeCommand(ServerConnection connection, string fullUrn, string[] arguments) + { + WriteToConsole(ConsoleColor.Yellow, "Invoking '{1}' on '{0}'...", fullUrn, arguments[0]); + try + { + var result = connection.Invoke(fullUrn, arguments[0], arguments.Skip(1).ToArray()); + WriteToConsole(ConsoleColor.Yellow, "...completed"); + } + catch (Exception error) + { + WriteToConsole(ConsoleColor.Red, "...failed: " + error.Message); + } } } } diff --git a/Playground/CruiseControl.Common/CruiseControl.Common.csproj b/Playground/CruiseControl.Common/CruiseControl.Common.csproj index b78a79582..8d7de7171 100644 --- a/Playground/CruiseControl.Common/CruiseControl.Common.csproj +++ b/Playground/CruiseControl.Common/CruiseControl.Common.csproj @@ -43,6 +43,8 @@ + + diff --git a/Playground/CruiseControl.Common/Messages/ServerItem.cs b/Playground/CruiseControl.Common/Messages/ServerItem.cs new file mode 100644 index 000000000..de14d9415 --- /dev/null +++ b/Playground/CruiseControl.Common/Messages/ServerItem.cs @@ -0,0 +1,40 @@ +namespace CruiseControl.Common.Messages +{ + /// + /// An item on the server. + /// + public class ServerItem + { + #region Public properties + #region DisplayName + /// + /// Gets or sets the display name. + /// + /// + /// The display name. + /// + public string DisplayName { get; set; } + #endregion + + #region Urn + /// + /// Gets or sets the URN. + /// + /// + /// The URN of the item. + /// + public string Urn { get; set; } + #endregion + + #region Description + /// + /// Gets or sets the description. + /// + /// + /// The description. + /// + public string Description { get; set; } + #endregion + #endregion + } +} diff --git a/Playground/CruiseControl.Common/Messages/ServerItemList.cs b/Playground/CruiseControl.Common/Messages/ServerItemList.cs new file mode 100644 index 000000000..72534c965 --- /dev/null +++ b/Playground/CruiseControl.Common/Messages/ServerItemList.cs @@ -0,0 +1,20 @@ +namespace CruiseControl.Common.Messages +{ + /// + /// A blank message. + /// + public class ServerItemList + { + #region Public properties + #region Children + /// + /// Gets or sets the children. + /// + /// + /// The children. + /// + public ServerItem[] Children { get; set; } + #endregion + #endregion + } +} diff --git a/Playground/CruiseControl.Console/CruiseControl.Console.csproj b/Playground/CruiseControl.Console/CruiseControl.Console.csproj index 3e6cf2053..be5a77046 100644 --- a/Playground/CruiseControl.Console/CruiseControl.Console.csproj +++ b/Playground/CruiseControl.Console/CruiseControl.Console.csproj @@ -50,6 +50,10 @@ + + {166D519E-854D-4405-9FAE-C6825CF7BBE6} + CruiseControl.Common + {74405CD5-BD3D-4912-A465-F929FA20220B} CruiseControl.Core diff --git a/Playground/CruiseControl.Core.Tests/ServerTests.cs b/Playground/CruiseControl.Core.Tests/ServerTests.cs index 9142bb2b4..62d9a42b3 100644 --- a/Playground/CruiseControl.Core.Tests/ServerTests.cs +++ b/Playground/CruiseControl.Core.Tests/ServerTests.cs @@ -188,6 +188,17 @@ public void CloseCommunicationsCleansUpEachChannel() server.CloseCommunications(); Assert.IsTrue(cleaned); } + + [Test] + public void ListProjectsIncludesAllProjects() + { + var server = new Server( + "test", + new Project("project1"), + new Project("project2")); + var result = server.ListProjects(null); + Assert.AreEqual(2, result.Children.Length); + } #endregion } } diff --git a/Playground/CruiseControl.Core/Server.cs b/Playground/CruiseControl.Core/Server.cs index 69ab5de1f..8cf882e88 100644 --- a/Playground/CruiseControl.Core/Server.cs +++ b/Playground/CruiseControl.Core/Server.cs @@ -11,6 +11,7 @@ using CruiseControl.Core.Utilities; using Ninject; using NLog; + using Messages = CruiseControl.Common.Messages; /// /// The root configuration node. @@ -235,6 +236,34 @@ public virtual void Validate(IValidationLog validationLog) #endregion #endregion + #region Actions + #region ListProjects() + /// + /// Lists the projects on the server. + /// + /// The request containing the details. + /// A message containing the response details. + [RemoteAction] + [Description("Lists the projects on the server.")] + public virtual Messages.ServerItemList ListProjects(Messages.Blank request) + { + var projects = this.Children.SelectMany(c => c.ListProjects()); + var response = new Messages.ServerItemList + { + Children = projects + .Select(p => new Messages.ServerItem + { + Description = p.Description, + DisplayName = p.Name, + Urn = p.UniversalName + }) + .ToArray() + }; + return response; + } + #endregion + #endregion + #region Private methods #region LocateInChildren() /// diff --git a/Playground/CruiseControl.Core/ServerItem.cs b/Playground/CruiseControl.Core/ServerItem.cs index 8f9f5a590..a55ee1db9 100644 --- a/Playground/CruiseControl.Core/ServerItem.cs +++ b/Playground/CruiseControl.Core/ServerItem.cs @@ -42,6 +42,14 @@ protected ServerItem(string name) public string Name { get; set; } #endregion + #region Description + /// + /// Gets the description. + /// + [DefaultValue(null)] + public string Description { get; set; } + #endregion + #region ItemType /// /// Gets the type of the item.