Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature compose project dir #217

Merged
merged 4 commits into from
Sep 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions Ductus.FluentDocker.Tests/CommandTests/ComposeCommandTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Ductus.FluentDocker.Commands;
using Ductus.FluentDocker.Extensions;
using Ductus.FluentDocker.Model.Common;
using Ductus.FluentDocker.Services;
using Ductus.FluentDocker.Services.Extensions;
using Ductus.FluentDocker.Services.Impl;
using Ductus.FluentDocker.Tests.Compose;
Expand Down Expand Up @@ -33,7 +31,13 @@ public async Task

try
{
var result = DockerHost.Host.ComposeUp(composeFile: file, certificates: DockerHost.Certificates);
var result = DockerHost.Host
.ComposeUpCommand(new Commands.Compose.ComposeUpCommandArgs
{
ComposeFiles = new System.Collections.Generic.List<string>() { file },
Certificates = DockerHost.Certificates
});

Assert.IsTrue(result.Success);

var ids = DockerHost.Host.ComposePs(composeFile: file, certificates: DockerHost.Certificates);
Expand Down Expand Up @@ -83,8 +87,13 @@ public void Issue79_DockerComposeOnDockerMachineShallWork()
typeof(NsResolver).ResourceExtract(fullPath);

var hostService = new DockerHostService("wifi-test");

var composeResponse = hostService.Host
.ComposeUp(composeFile: file, certificates: hostService.Certificates);
.ComposeUpCommand(new Commands.Compose.ComposeUpCommandArgs
{
ComposeFiles = new System.Collections.Generic.List<string>() { file },
Certificates = hostService.Certificates
});
}
}
}
11 changes: 11 additions & 0 deletions Ductus.FluentDocker/Builders/CompositeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@ public CompositeBuilder FromFile(params string[] composeFile)
return this;
}

/// <summary>
/// Explicitly sets the project directory.
/// </summary>
/// <param name="projectDir">The project dir, if none set it to an empty string.</param>
/// <returns>Itself for fluent access.</returns>
public CompositeBuilder UseProjectDir(TemplateString projectDir)
{
_config.ProjectDirectory = projectDir;
return this;
}

public CompositeBuilder ForceRecreate()
{
_config.ForceRecreate = true;
Expand Down
86 changes: 65 additions & 21 deletions Ductus.FluentDocker/Commands/Compose.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Ductus.FluentDocker.Executors;
using Ductus.FluentDocker.Executors.Parsers;
using Ductus.FluentDocker.Extensions;
Expand Down Expand Up @@ -406,64 +407,107 @@ public static CommandResponse<IList<string>> ComposeDown(this DockerUri host, st
$"{args} down {options}", cwd.NeedCwd ? cwd.Cwd : null).ExecutionEnvironment(env).Execute();
}

[Obsolete("Use ComposeUpCommand(...)")]
public static CommandResponse<IList<string>> ComposeUp(this DockerUri host,
string altProjectName = null,
bool forceRecreate = false, bool noRecreate = false, bool dontBuild = false,
bool buildBeforeCreate = false, TimeSpan? timeout = null,
bool removeOphans = false,
bool removeOrphans = false,
bool useColor = false,
bool noStart = false,
string[] services = null /*all*/,
IDictionary<string, string> env = null,
ICertificatePaths certificates = null, params string[] composeFile)
{
if (forceRecreate && noRecreate)
return host.ComposeUpCommand(new ComposeUpCommandArgs
{
throw new InvalidOperationException($"{nameof(forceRecreate)} and {nameof(noRecreate)} are incompatible.");
AltProjectName = altProjectName,
ForceRecreate = forceRecreate,
NoRecreate = noRecreate,
DontBuild = dontBuild,
BuildBeforeCreate = buildBeforeCreate,
Timeout = timeout,
RemoveOrphans = removeOrphans,
UseColor = useColor,
NoStart = noStart,
Services = services,
Env = env,
Certificates = certificates,
ComposeFiles = composeFile
});
}

public struct ComposeUpCommandArgs
{
public string AltProjectName {get;set;}
public bool ForceRecreate {get;set;}
public bool NoRecreate {get;set;}
public bool DontBuild {get;set;}
public bool BuildBeforeCreate {get;set;}
public TimeSpan? Timeout {get;set;}
public bool RemoveOrphans {get;set;}
public bool UseColor {get;set;}
public bool NoStart {get;set;}
public IList<string> Services {get;set;}
public IDictionary<string, string> Env {get;set;}
public ICertificatePaths Certificates {get;set;}
public IList<string> ComposeFiles {get;set;}
public TemplateString ProjectDirectory {get;set;}
}

public static CommandResponse<IList<string>> ComposeUpCommand(this DockerUri host, ComposeUpCommandArgs ca)
{
if (ca.ForceRecreate && ca.NoRecreate)
{
throw new InvalidOperationException("ForceRecreate and NoRecreate are incompatible.");
}

var cwd = WorkingDirectory(composeFile);
var cwd = WorkingDirectory(ca.ComposeFiles.ToArray());

var args = $"{host.RenderBaseArgs(certificates)}";
var args = $"{host.RenderBaseArgs(ca.Certificates)}";

if (null != composeFile && 0 != composeFile.Length)
foreach (var cf in composeFile)
if (null != ca.ComposeFiles && 0 != ca.ComposeFiles.Count)
foreach (var cf in ca.ComposeFiles)
if (!string.IsNullOrEmpty(cf))
args += $" -f \"{cf}\"";

if (!string.IsNullOrEmpty(altProjectName))
args += $" -p {altProjectName}";
if (!string.IsNullOrEmpty(ca.AltProjectName))
args += $" -p {ca.AltProjectName}";

var options = noStart ? "--no-start" : "--detach";
var options = ca.NoStart ? "--no-start" : "--detach";

if (forceRecreate)
if (ca.ForceRecreate)
options += " --force-recreate";

if (noRecreate)
if (ca.NoRecreate)
options += " --no-recreate";

if (dontBuild)
if (ca.DontBuild)
options += " --no-build";

if (buildBeforeCreate)
if (ca.BuildBeforeCreate)
options += " --build";

if (!useColor)
if (!ca.UseColor)
options += " --no-color";

if (null != timeout)
options += $" -t {Math.Round(timeout.Value.TotalSeconds, 0)}";
if (null != ca.Timeout)
options += $" -t {Math.Round(ca.Timeout.Value.TotalSeconds, 0)}";

if (removeOphans)
if (ca.RemoveOrphans)
options += " --remove-orphans";

if (null != services && 0 != services.Length)
options += " " + string.Join(" ", services);
if (!string.IsNullOrEmpty(ca.ProjectDirectory)) {
options += $" --project-directory {ca.ProjectDirectory.Rendered}";
}

if (null != ca.Services && 0 != ca.Services.Count)
options += " " + string.Join(" ", ca.Services);

return
new ProcessExecutor<StringListResponseParser, IList<string>>(
"docker-compose".ResolveBinary(),
$"{args} up {options}", cwd.NeedCwd ? cwd.Cwd : null).ExecutionEnvironment(env).Execute();
$"{args} up {options}", cwd.NeedCwd ? cwd.Cwd : null).ExecutionEnvironment(ca.Env).Execute();
}

public static CommandResponse<IList<string>> ComposeRm(this DockerUri host, string altProjectName = null,
Expand Down
2 changes: 2 additions & 0 deletions Ductus.FluentDocker/Model/Compose/DockerComposeConfig.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Ductus.FluentDocker.Model.Images;
using Ductus.FluentDocker.Model.Common;

namespace Ductus.FluentDocker.Model.Compose
{
Expand All @@ -24,6 +25,7 @@ public class DockerComposeConfig
public bool StopOnDispose { get; set; } = true;
public bool KeepContainers { get; set; }
public IDictionary<string, string> EnvironmentNameValue { get; set; } = new Dictionary<string, string>();
public TemplateString ProjectDirectory {get;set;}

public IDictionary<string, ContainerSpecificConfig> ContainerConfiguration { get; } =
new Dictionary<string, ContainerSpecificConfig>();
Expand Down
53 changes: 37 additions & 16 deletions Ductus.FluentDocker/Services/Impl/DockerComposeCompositeService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Ductus.FluentDocker.Extensions;
using Ductus.FluentDocker.Model.Compose;
using Ductus.FluentDocker.Model.Containers;
using static Ductus.FluentDocker.Commands.Compose;

namespace Ductus.FluentDocker.Services.Impl
{
Expand Down Expand Up @@ -129,14 +130,24 @@ public override void Start()

State = ServiceRunningState.Starting;

var result = host.Host.ComposeUp(_config.AlternativeServiceName, _config.ForceRecreate,
_config.NoRecreate, _config.NoBuild, _config.ForceBuild,
_config.TimeoutSeconds == TimeSpan.Zero ? (TimeSpan?)null : _config.TimeoutSeconds, _config.RemoveOrphans,
_config.UseColor,
true/*noStart*/,
_config.Services,
_config.EnvironmentNameValue,
host.Certificates, _config.ComposeFilePath.ToArray());
var result = host.Host.ComposeUpCommand(
new ComposeUpCommandArgs
{
AltProjectName = _config.AlternativeServiceName,
ForceRecreate = _config.ForceRecreate,
NoRecreate = _config.NoRecreate,
DontBuild = _config.NoBuild,
BuildBeforeCreate = _config.ForceBuild,
Timeout = _config.TimeoutSeconds == TimeSpan.Zero ? (TimeSpan?)null : _config.TimeoutSeconds,
RemoveOrphans = _config.RemoveOrphans,
UseColor = _config.UseColor,
NoStart = true,
Services = _config.Services,
Env = _config.EnvironmentNameValue,
Certificates = host.Certificates,
ComposeFiles = _config.ComposeFilePath.ToArray(),
ProjectDirectory = _config.ProjectDirectory
});

if (!result.Success)
{
Expand All @@ -147,14 +158,24 @@ public override void Start()

State = ServiceRunningState.Starting;

result = host.Host.ComposeUp(_config.AlternativeServiceName,
false/*forceRecreate*/, false/*noRecreate*/, false/*dontBuild*/, false/*buildBeforeCreate*/,
_config.TimeoutSeconds == TimeSpan.Zero ? (TimeSpan?)null : _config.TimeoutSeconds, _config.RemoveOrphans,
_config.UseColor,
false/*noStart*/,
_config.Services,
_config.EnvironmentNameValue,
host.Certificates, _config.ComposeFilePath.ToArray());
result = host.Host.ComposeUpCommand(
new ComposeUpCommandArgs
{
AltProjectName = _config.AlternativeServiceName,
ForceRecreate = false,
NoRecreate = false,
DontBuild = false,
BuildBeforeCreate = false,
Timeout = _config.TimeoutSeconds == TimeSpan.Zero ? (TimeSpan?)null : _config.TimeoutSeconds,
RemoveOrphans = _config.RemoveOrphans,
UseColor = _config.UseColor,
NoStart = false,
Services = _config.Services,
Env = _config.EnvironmentNameValue,
Certificates = host.Certificates,
ComposeFiles = _config.ComposeFilePath.ToArray(),
ProjectDirectory = _config.ProjectDirectory
});

if (!result.Success)
{
Expand Down
26 changes: 26 additions & 0 deletions Examples/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Simple/bin/Debug/netcoreapp3.1/Simple.dll",
"args": [],
"cwd": "${workspaceFolder}/Simple",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}
14 changes: 14 additions & 0 deletions Examples/Examples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DockerInDockerLinux", "Dock
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventDriven", "EventDriven\EventDriven.csproj", "{75D101EB-5CE3-457E-8843-76898CB5513B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simple", "Simple\Simple.csproj", "{25359F72-CCB4-4373-9857-D0AC45F8510F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -44,5 +46,17 @@ Global
{75D101EB-5CE3-457E-8843-76898CB5513B}.Release|x64.Build.0 = Release|Any CPU
{75D101EB-5CE3-457E-8843-76898CB5513B}.Release|x86.ActiveCfg = Release|Any CPU
{75D101EB-5CE3-457E-8843-76898CB5513B}.Release|x86.Build.0 = Release|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Debug|x64.ActiveCfg = Debug|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Debug|x64.Build.0 = Debug|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Debug|x86.ActiveCfg = Debug|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Debug|x86.Build.0 = Debug|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Release|Any CPU.Build.0 = Release|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Release|x64.ActiveCfg = Release|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Release|x64.Build.0 = Release|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Release|x86.ActiveCfg = Release|Any CPU
{25359F72-CCB4-4373-9857-D0AC45F8510F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Loading