Skip to content

Commit

Permalink
Merge pull request #3 from syncromatics/feature/ps-command
Browse files Browse the repository at this point in the history
Added support for ps command
  • Loading branch information
derrickcrowne authored Dec 6, 2016
2 parents b6b5eb5 + c376d4f commit 830c914
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 11 deletions.
15 changes: 15 additions & 0 deletions src/LclDckr/Commands/Ps/ContainerInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Collections.Generic;

namespace LclDckr.Commands.Ps
{
public class ContainerInfo
{
public string ContainerId { get; set; }
public string Image { get; set; }
public string Command { get; set; }
public string Created { get; set; }
public string Status { get; set; }
public string Ports { get; set; }
public List<string> Names { get; set; }
}
}
58 changes: 58 additions & 0 deletions src/LclDckr/Commands/Ps/ContainerInfoParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace LclDckr.Commands.Ps
{
/// <summary>
/// Parses output of Ps command
/// </summary>
internal class ContainerInfoParser
{
private readonly string[] _expectedHeaders =
{
"CONTAINER ID",
"IMAGE",
"COMMAND",
"CREATED",
"STATUS",
"PORTS",
"NAMES"
};

private readonly Tuple<int, int>[] _fieldLocations;

public ContainerInfoParser(string headers)
{
_fieldLocations = new Tuple<int, int>[_expectedHeaders.Length];

for (int i = 0; i < _expectedHeaders.Length; i++)
{
var idRegex = new Regex($"({_expectedHeaders[i]}) *");
var match = idRegex.Match(headers);
if (!match.Success)
{
throw new Exception($"Returned headers from ps command did not match expected headers {headers}");
}

_fieldLocations[i] = Tuple.Create(match.Index, match.Length);
}
}

public ContainerInfo Parse(string fields)
{
Func<int, string> getField = i => fields.Substring(_fieldLocations[i].Item1, i < _fieldLocations.Length - 1 ? _fieldLocations[i].Item2 : fields.Length - _fieldLocations[i].Item1);

return new ContainerInfo
{
ContainerId = getField(0).Trim(),
Image = getField(1).Trim(),
Command = getField(2).Trim(),
Created = getField(3).Trim(),
Status = getField(4).Trim(),
Ports = getField(5).Trim(),
Names = getField(6).Trim().Split(',').ToList()
};
}
}
}
7 changes: 7 additions & 0 deletions src/LclDckr/Commands/Ps/Filters/IFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace LclDckr.Commands.Ps.Filters
{
public interface IFilter
{
string Value { get; }
}
}
18 changes: 18 additions & 0 deletions src/LclDckr/Commands/Ps/Filters/NameFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace LclDckr.Commands.Ps.Filters
{
public class NameFilter : IFilter
{
public string Name { get; set; }
public string Value => $"name={Name}";

public NameFilter()
{

}

public NameFilter(string name)
{
Name = name;
}
}
}
81 changes: 79 additions & 2 deletions src/LclDckr/DockerClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using System.Diagnostics;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using LclDckr.Commands.Ps;
using LclDckr.Commands.Ps.Filters;

namespace LclDckr
{
Expand All @@ -21,6 +25,14 @@ public string Build(string path = ".")
.Last();
}

/// <summary>
/// Runs the specified image in a new container
/// </summary>
/// <param name="imageName"></param>
/// <param name="name"></param>
/// <param name="hostName"></param>
/// <param name="interactive"></param>
/// <returns>The long uuid of the created container</returns>
public string RunImage(string imageName, string name, string hostName = null, bool interactive = false)
{
var hostArg = hostName != null ? $"--hostname {hostName}" : "";
Expand All @@ -36,7 +48,12 @@ public string RunImage(string imageName, string name, string hostName = null, bo
return process.StandardOutput.ReadToEnd();
}

public void PullImage(string imageName, string tag)
/// <summary>
/// Pulls the specified image.
/// </summary>
/// <param name="imageName"></param>
/// <param name="tag"></param>
public void PullImage(string imageName, string tag = "latest")
{
var args = $"pull {imageName}:{tag}";

Expand All @@ -46,6 +63,11 @@ public void PullImage(string imageName, string tag)
process.ThrowForError();
}

/// <summary>
/// starts an existing container by name
/// </summary>
/// <param name="name"></param>
/// <returns>the name of the started container</returns>
public string StartContainer(string name)
{
var args = $"start {name}";
Expand All @@ -58,6 +80,11 @@ public string StartContainer(string name)
return process.StandardOutput.ReadToEnd();
}

/// <summary>
/// stops an existing container by name
/// </summary>
/// <param name="name"></param>
/// <returns>the name of the stopped container</returns>
public string StopContainer(string name)
{
var args = $"stop {name}";
Expand All @@ -69,6 +96,11 @@ public string StopContainer(string name)
return process.StandardOutput.ReadToEnd();
}

/// <summary>
/// removes an existing container by name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public string RemoveContainer(string name)
{
var args = $"rm {name}";
Expand All @@ -80,6 +112,51 @@ public string RemoveContainer(string name)
return process.StandardOutput.ReadToEnd();
}

/// <summary>
/// Returns info on this systems containers
/// </summary>
/// <param name="all">true for all containers, false for running containers only</param>
/// <param name="filters"></param>
/// <returns></returns>
public ICollection<ContainerInfo> Ps(bool all = false, IEnumerable<IFilter> filters = null)
{
var args = new StringBuilder("ps");

if (all)
{
args.Append(" -a");
}

if (filters != null)
{
foreach (var filter in filters)
{
args.Append($" --filter \"{filter.Value}\"");
}
}

var process = GetDockerProcess(args.ToString());

process.Start();
process.WaitForExit();
process.ThrowForError();

var headers = process.StandardOutput.ReadLine();

var parser = new ContainerInfoParser(headers);

var containers = new List<ContainerInfo>();

while (!process.StandardOutput.EndOfStream)
{
var fields = process.StandardOutput.ReadLine();
var container = parser.Parse(fields);
containers.Add(container);
}

return containers;
}

private Process GetDockerProcess(string arguments)
{
return new Process
Expand Down
12 changes: 9 additions & 3 deletions src/LclDckr/project.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
{
"version": "1.0.0-*",
"version": "1.0.1-*",
"description": "A dotnet wrapper around the docker cli.",
"authors": ["Syncromatics"],

"authors": ["Syncromatics"],
"packOptions": {
"tags": [
"Docker",
"Local Docker",
"Docker Cli"
]
},
"dependencies": {

},
Expand Down
24 changes: 19 additions & 5 deletions test/LclDckr.IntegrationTests/DockerClientTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Xunit;
using System.Linq;
using LclDckr.Commands.Ps.Filters;
using Xunit;

namespace LclDckr.IntegrationTests
{
Expand All @@ -8,15 +10,27 @@ public class DockerClientTests
public void Pulls_runs_stops_image()
{
var client = new DockerClient();
client.PullImage("ubuntu", "latest");
client.PullImage("ubuntu");

var id = client.RunImage("ubuntu", "test-container", interactive: true);
var containerName = "lcldckr-test-container";

var id = client.RunImage("ubuntu", containerName, interactive: true);
Assert.NotNull(id);

id = client.StopContainer("test-container");
var runningContainer = client
.Ps(true, new[] {new NameFilter(containerName)})
.SingleOrDefault();

Assert.NotNull(runningContainer);

Assert.Equal(containerName, runningContainer.Names.Single());

Assert.Equal(id.Substring(0, 12), runningContainer.ContainerId);

id = client.StopContainer(containerName);
Assert.NotNull(id);

id = client.RemoveContainer("test-container");
id = client.RemoveContainer(containerName);
Assert.NotNull(id);
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/LclDckr.IntegrationTests/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"testRunner": "xunit",
"dependencies": {
"xunit": "2.2.0-beta4-build3444",
"LclDckr": "1.0.0-*",
"LclDckr": "1.0.1-*",
"dotnet-test-xunit": "2.2.0-preview2-build1029"
},
"frameworks": {
Expand Down

0 comments on commit 830c914

Please sign in to comment.