Skip to content

Commit

Permalink
Merge pull request #180 from mariotoffia/feature-filebuilder-misc
Browse files Browse the repository at this point in the history
Add features to Docker FileBuilder
  • Loading branch information
mariotoffia committed Mar 17, 2021
2 parents 0074eac + 08fe0ce commit 781c884
Show file tree
Hide file tree
Showing 13 changed files with 443 additions and 15 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"cSpell.words": [
"dont"
"Ductus",
"dont",
"myimg",
"mytag"
]
}
88 changes: 86 additions & 2 deletions Ductus.FluentDocker/Builders/FileBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,30 @@ public FileBuilder WorkingFolder(TemplateString workingFolder)
return this;
}

/// <summary>
/// Specified a simplified from command with the image name (and optional tag name) only!
/// </summary>
/// <param name="from">The image and optional tag name.</param>
/// <returns>Itself for fluent access.</returns>
public FileBuilder UseParent(string from)
{
_config.Commands.Add(new FromCommand(from));
return this;
}

/// <summary>
/// Specifies the _FROM_ command.
/// </summary>
/// <param name="imageAndTag">The image to derive from and a optional (colon) tag, e.g. myimg:mytag</param>
/// <param name="asName">An optional alias.</param>
/// <param name="platform">An optional platform such linux/amd64 or windows/amd64.</param>
/// <returns>Itself for fluent access.</returns>
public FileBuilder From(TemplateString imageAndTag, TemplateString asName = null, TemplateString platform = null)
{
_config.Commands.Add(new FromCommand(imageAndTag, asName, platform));
return this;
}

public FileBuilder Maintainer(string maintainer)
{
_config.Commands.Add(new MaintainerCommand(maintainer));
Expand Down Expand Up @@ -127,9 +145,22 @@ public FileBuilder WithHealthCheck(string cmd, string interval = null, string ti
return this;
}

public FileBuilder Copy(TemplateString source, TemplateString dest)
/// <summary>
/// This generates the _COPY_ command.
/// </summary>
/// <param name="source">From directory.</param>
/// <param name="dest">To directory.</param>
/// <param name="chownUserAndGroup">Optional --chown user:group.</param>
/// <param name="fromAlias">
/// Optional source location from earlier buildstage FROM ... AS alias. This will
/// generate --from=aliasname in the _COPY_ command and hence reference a earlier
/// _FROM ... AS aliasname_ buildstep as source.
/// </param>
/// <returns>Itself for fluent access.</returns>
public FileBuilder Copy(TemplateString source, TemplateString dest,
TemplateString chownUserAndGroup = null, TemplateString fromAlias = null)
{
_config.Commands.Add(new CopyCommand(source, dest));
_config.Commands.Add(new CopyCommand(source, dest, chownUserAndGroup, fromAlias));
return this;
}

Expand All @@ -145,6 +176,59 @@ public FileBuilder ExposePorts(params int[] ports)
return this;
}

/// <summary>
/// Adds a _ENV_ command to _dockerfile_. The value of each name value pair is automatically
/// double quoted. Hence, it is possible to write spaces etc in the string without double quoting it.
/// </summary>
/// <param name="nameValue">Name=value array.</param>
/// <returns>Itself for fluent access.</returns>
/// <remarks>The name value is separated by space on same line.</remarks>
public FileBuilder Environment(params TemplateString[] nameValue)
{
_config.Commands.Add(new EnvCommand(nameValue));
return this;
}

/// <summary>
/// Adds a _LABEL_ command to _dockerfile_. The value of each name value pair is automatically
/// double quoted. Hence, it is possible to write spaces etc in the string without double quoting it.
/// </summary>
/// <param name="nameValue">Name=value array.</param>
/// <returns>Itself for fluent access.</returns>
/// <remarks>The name value is separated by space on same line.</remarks>
public FileBuilder Label(params TemplateString[] nameValue)
{
_config.Commands.Add(new LabelCommand(nameValue));
return this;
}

/// <summary>
/// Adds a _ARG_ command in _dockerfile_ with the optional _defaultValue_.
/// </summary>
/// <param name="name">The name of the argument.</param>
/// <param name="defaultValue">Optional a default value for the argument.</param>
/// <returns>Itself for fluent access.</returns>
public FileBuilder Arguments(TemplateString name, TemplateString defaultValue = null) {
_config.Commands.Add(new ArgCommand(name, defaultValue));
return this;
}

public FileBuilder Entrypoint(string command, params string[] args)
{
_config.Commands.Add(new EntrypointCommand(command, args));
return this;
}

public FileBuilder User(TemplateString user, TemplateString group = null) {
_config.Commands.Add(new UserCommand(user, group));
return this;
}

public FileBuilder Volume(params TemplateString[] mountpoints) {
_config.Commands.Add(new VolumeCommand(mountpoints));
return this;
}

public FileBuilder Command(string command, params string[] args)
{
_config.Commands.Add(new CmdCommand(command, args));
Expand Down
19 changes: 17 additions & 2 deletions Ductus.FluentDocker/Builders/ImageBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,23 @@ protected override IBuilder InternalCreate()
return new ImageBuilder(this);
}

public FileBuilder From(string from)
{
/// <summary>
/// Creates a _dockerfile_ builder.
/// </summary>
/// <param name="from">
/// Optional image to specify as FROM. If omitted, it is up to the caller to specify _UseParent_ or _From_.
/// </param>
/// <returns>
/// A newly created filebuilder. If empty or null string the `FileBuilder` is empty. Otherwise it has populated
/// the `FileBuilder` with a parent of the specified image name (via _UseParent()_).
/// </returns>
public FileBuilder From(string from = null)
{
if (string.IsNullOrEmpty(from))
{
return _fileBuilder = new FileBuilder(this);
}

return _fileBuilder = new FileBuilder(this).UseParent(from);
}

Expand Down
33 changes: 33 additions & 0 deletions Ductus.FluentDocker/Extensions/EnvironmentExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Ductus.FluentDocker.Common;
using Ductus.FluentDocker.Executors;
using Ductus.FluentDocker.Model.Common;

namespace Ductus.FluentDocker.Extensions
{
Expand Down Expand Up @@ -33,5 +36,35 @@ public static class EnvironmentExtensions

return executor;
}

/// <summary>
/// This function will extract the name value and verify that is is valid. It will then
/// make sure that the value is wrapped inside double quotes if not yet wrapped.
/// </summary>
/// <param name="nameValue">The name=value strings</param>
/// <returns>A list of name=value string with the value wrapped inside double quotes.</returns>
public static IList<string> WrapValue(this TemplateString[] nameValue)
{

var list = new List<string>();
foreach (var s in nameValue.Select(s => s.Rendered))
{

var index = s.IndexOf('=');
if (-1 == index)
{
throw new FluentDockerException(
$"Expected format name=value, missing equal sign in the name value string: '{s}'"
);
}

var name = s.Substring(0, index);
var value = s.Substring(index + 1, s.Length - index - 1).WrapWithChar("\"");

list.Add($"{name}={value}");
}

return list;
}
}
}
26 changes: 26 additions & 0 deletions Ductus.FluentDocker/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

namespace Ductus.FluentDocker.Extensions {
public static class StringExtensions {

/// <summary>
/// This function will wrap the string s with string c (start and end) if
/// not already existant. If already exist, it will leave it, hence it
/// do not double wrap.
/// </summary>
/// <param name="s">The string to wrap.</param>
/// <param name="c">The string to check and wrap with if not existing.</param>
/// <returns>The wrapped string.</returns>
public static string WrapWithChar(this string s, string c) {

if (!s.StartsWith(c)) {
s = c + s;
}

if (!s.EndsWith(c)) {
s = s + c;
}

return s;
}
}
}
41 changes: 41 additions & 0 deletions Ductus.FluentDocker/Model/Builders/FileBuilder/ArgCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Ductus.FluentDocker.Common;
using Ductus.FluentDocker.Extensions;
using Ductus.FluentDocker.Model.Common;

namespace Ductus.FluentDocker.Model.Builders.FileBuilder
{
public sealed class ArgCommand : ICommand
{
public ArgCommand(TemplateString name, TemplateString defaultValue = null)
{
if (null == name || string.IsNullOrEmpty(name.Rendered))
{
throw new FluentDockerException("Must, at least, specify the argument name in a ARG");
}


Name = name.Rendered;

if (null != defaultValue && !string.IsNullOrEmpty(defaultValue.Rendered))
{
DefaultValue = defaultValue.Rendered;
}
}

public string Name { get; }
public string DefaultValue { get; }

public override string ToString()
{
if (string.IsNullOrEmpty(DefaultValue))
{
return $"ARG {Name}";
}

return $"ARG {Name}={DefaultValue}";
}
}
}
45 changes: 40 additions & 5 deletions Ductus.FluentDocker/Model/Builders/FileBuilder/CopyCommand.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,54 @@
namespace Ductus.FluentDocker.Model.Builders.FileBuilder
using Ductus.FluentDocker.Extensions;
using Ductus.FluentDocker.Model.Common;

namespace Ductus.FluentDocker.Model.Builders.FileBuilder
{
public sealed class CopyCommand : ICommand
{
public CopyCommand(string from, string to)
/// <summary>
/// This generates the _COPY_ command.
/// </summary>
/// <param name="from">From directory.</param>
/// <param name="to">To directory.</param>
/// <param name="chownUserAndGroup">Optional --chown user:group.</param>
/// <param name="fromAlias">
/// Optional source location from earlier buildstage FROM ... AS alias. This will
/// generate --from=aliasname in the _COPY_ command and hence reference a earlier
/// _FROM ... AS aliasname_ buildstep as source.
/// </param>
public CopyCommand(TemplateString from, TemplateString to,
TemplateString chownUserAndGroup = null, TemplateString fromAlias = null)
{
From = from;
To = to;
From = from.Rendered.WrapWithChar("\"");
To = to.Rendered.WrapWithChar("\"");

if (null != chownUserAndGroup && !string.IsNullOrEmpty(chownUserAndGroup.Rendered)) {
Chown = chownUserAndGroup.Rendered;
}

if (null != fromAlias && !string.IsNullOrEmpty(fromAlias.Rendered)) {
Alias = fromAlias.Rendered;
}
}

public string From { get; }
public string To { get; }
public string Alias { get; }
public string Chown { get; }

public override string ToString()
{
return $"COPY {From} {To}";
string s = "COPY";

if (!string.IsNullOrEmpty(Chown)) {
s = $"{s} --chown={Chown}";
}

if (!string.IsNullOrEmpty(Alias)) {
s = $"{s} --from={Alias}";
}

return $"{s} [{From},{To}]";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;

namespace Ductus.FluentDocker.Model.Builders.FileBuilder
{
public sealed class EntrypointCommand : ICommand
{
public EntrypointCommand(string executable, params string[] args)
{
Executable = executable;
Arguments = args ?? Array.Empty<string>();
}

public string Executable { get; }
public string[] Arguments { get; }

public override string ToString()
{
return $"ENTRYPOINT [\"{Executable}{string.Join("\",\"", Arguments)}\"]";
}
}
}
29 changes: 29 additions & 0 deletions Ductus.FluentDocker/Model/Builders/FileBuilder/EnvCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Ductus.FluentDocker.Extensions;
using Ductus.FluentDocker.Model.Common;
using System.Linq;

namespace Ductus.FluentDocker.Model.Builders.FileBuilder
{
public sealed class EnvCommand : ICommand
{
public EnvCommand(params TemplateString[] nameValue)
{
if (nameValue == null || 0 == nameValue.Length) {
NameValue = new string[0];
} else {
NameValue = NameValue = nameValue.WrapValue().ToArray();
}
}

public string[] NameValue { get; internal set; }

public override string ToString()
{
if (0 == NameValue.Length) {
return "";
}

return $"ENV {string.Join(" ", NameValue)}";
}
}
}
Loading

0 comments on commit 781c884

Please sign in to comment.