mirror of https://github.com/dotnet/tye.git
committed by
GitHub
81 changed files with 169 additions and 753 deletions
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class ApplicationGlobals |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class BuildDockerImageStep : ServiceExecutor.Step |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class CombineStep : ServiceExecutor.Step |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal class CommandException : Exception |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public class ComputedBindings : ServiceOutput |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class ContainerInfo |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class ContainerRegistry |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public enum DeploymentKind |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System.IO; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public static class DirectoryCopy |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class DockerImage : Source |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public class EnvironmentAttribute : Attribute |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public static class Environments |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class Framework |
|||
{ |
|||
@ -1,7 +1,7 @@ |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal sealed class GenerateDockerfileStep : ServiceExecutor.Step |
|||
{ |
|||
@ -1,7 +1,7 @@ |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal sealed class GenerateHelmChartStep : ServiceExecutor.Step |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class GenerateKubernetesManifestStep : ServiceExecutor.Step |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal sealed class GenerateOamComponentStep : ServiceExecutor.Step |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class GeneratedAssets |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class HelmChartStep : Step |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using YamlDotNet.RepresentationModel; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal interface IYamlManifestOutput |
|||
{ |
|||
@ -1,7 +1,7 @@ |
|||
using System; |
|||
using YamlDotNet.RepresentationModel; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal sealed class KubernetesDeploymentOutput : ServiceOutput, IYamlManifestOutput |
|||
{ |
|||
@ -1,7 +1,7 @@ |
|||
using System; |
|||
using YamlDotNet.RepresentationModel; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal sealed class KubernetesServiceOutput : ServiceOutput, IYamlManifestOutput |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal static class Names |
|||
{ |
|||
@ -1,7 +1,7 @@ |
|||
using System; |
|||
using YamlDotNet.RepresentationModel; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal sealed class OamComponentOutput : ServiceOutput, IYamlManifestOutput |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class PipelineHolder |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
static class Program |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class Project : Source |
|||
{ |
|||
@ -1,7 +1,7 @@ |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class PushDockerImageStep : ServiceExecutor.Step |
|||
{ |
|||
@ -1,8 +1,8 @@ |
|||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ImportGroup Condition=" '$(TargetFramework)' == '' AND '$(ExcludeRestorePackageImports)' != 'true' "> |
|||
<Import Project="$(OpulenceTargetLocation)\buildMultiTargeting\Opulence.targets" Condition="'$(OpulenceTargetLocation)'!=''" /> |
|||
<Import Project="$(TyeTargetLocation)\buildMultiTargeting\Tye.targets" Condition="'$(TyeTargetLocation)'!=''" /> |
|||
</ImportGroup> |
|||
<ImportGroup Condition=" '$(TargetFramework)' != '' AND '$(ExcludeRestorePackageImports)' != 'true' "> |
|||
<Import Project="$(OpulenceTargetLocation)\build\Opulence.targets" Condition="'$(OpulenceTargetLocation)'!=''" /> |
|||
<Import Project="$(TyeTargetLocation)\build\Tye.targets" Condition="'$(TyeTargetLocation)'!=''" /> |
|||
</ImportGroup> |
|||
</Project> |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public class Secret |
|||
{ |
|||
@ -1,7 +1,7 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public sealed class Service |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public class ServiceBinding |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public abstract class Source |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public abstract class Step |
|||
{ |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal class StepView |
|||
{ |
|||
@ -1,6 +1,6 @@ |
|||
using System.IO; |
|||
|
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
internal static class Templates |
|||
{ |
|||
@ -0,0 +1,34 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RootNamespace>Tye</RootNamespace> |
|||
<LangVersion>8.0</LangVersion> |
|||
<Nullable>Enable</Nullable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="KubernetesClient" Version="1.6.11" /> |
|||
<PackageReference Include="semver" Version="2.0.6" /> |
|||
<PackageReference Include="Sln" Version="0.3.0" /> |
|||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20071.2" /> |
|||
<PackageReference Include="System.Commandline.Rendering" Version="0.3.0-alpha.20070.2" /> |
|||
<PackageReference Include="YamlDotNet" Version="8.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Content Include="build\**" CopyToOutputDirectory="PreserveNewest" /> |
|||
<Content Include="buildMultiTargeting\**" CopyToOutputDirectory="PreserveNewest" /> |
|||
<Content Include="Templates\**" CopyToOutputDirectory="PreserveNewest" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Include="..\tye\TempDirectory.cs" Link="TempDirectory.cs" /> |
|||
<Compile Include="..\tye\TempFile.cs" Link="TempFile.cs" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="Resources\Imports.targets" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,4 +1,4 @@ |
|||
namespace Opulence |
|||
namespace Tye |
|||
{ |
|||
public enum Verbosity |
|||
{ |
|||
@ -1,13 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<LangVersion>8.0</LangVersion> |
|||
<Nullable>Enable</Nullable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="System.Text.Json" Version="4.7.0" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -1,142 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Build.Construction; |
|||
|
|||
namespace Opulence |
|||
{ |
|||
public static class ApplicationFactory |
|||
{ |
|||
public static async Task<Application> CreateApplicationAsync(OutputContext output, FileInfo projectFile) |
|||
{ |
|||
if (output is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(output)); |
|||
} |
|||
|
|||
if (projectFile is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(projectFile)); |
|||
} |
|||
|
|||
if (string.Equals(projectFile.Extension, ".sln", StringComparison.Ordinal)) |
|||
{ |
|||
output.WriteDebugLine($"Solution '{projectFile.FullName}' was provided as input."); |
|||
return await CreateApplicationForSolutionAsync(output, projectFile); |
|||
} |
|||
else |
|||
{ |
|||
output.WriteDebugLine($"Project '{projectFile.FullName}' was provided as input."); |
|||
return await CreateApplicationForProjectAsync(output, projectFile); |
|||
} |
|||
} |
|||
|
|||
private static async Task<Application> CreateApplicationForProjectAsync(OutputContext output, FileInfo projectFile) |
|||
{ |
|||
// Project workflow:
|
|||
//
|
|||
// 1. Determine if there's an 'Opulence.csx' - use that to initialize the set of services.
|
|||
// 2. If there's not an 'Opulence.csx' then move on with just the project.
|
|||
|
|||
var application = await ScriptRunner.RunCustomizationScriptAsync(output, projectFile); |
|||
if (application != null) |
|||
{ |
|||
return application; |
|||
} |
|||
|
|||
return await InferApplicationForProject(output, projectFile); |
|||
} |
|||
|
|||
private static async Task<Application> InferApplicationForProject(OutputContext output, FileInfo projectFile) |
|||
{ |
|||
var globals = new ApplicationGlobals(); |
|||
globals.Name = Names.NormalizeToDns(Path.GetFileNameWithoutExtension(projectFile.Name)); |
|||
|
|||
var services = new List<ServiceEntry>(); |
|||
|
|||
var name = Path.GetFileNameWithoutExtension(projectFile.Name); |
|||
var project = new Project(projectFile.FullName); |
|||
var service = new ServiceEntry(new Service(name), name); |
|||
service.Service.Source = project; |
|||
services.Add(service); |
|||
|
|||
await ProjectReader.ReadProjectDetailsAsync(output, projectFile, project); |
|||
|
|||
var container = new ContainerInfo(); |
|||
service.Service.GeneratedAssets.Container = container; |
|||
|
|||
var application = new GroveledApplication(globals, projectFile.DirectoryName, services); |
|||
|
|||
DockerfileGenerator.ApplyContainerDefaults(application, service, project, container); |
|||
|
|||
return application; |
|||
} |
|||
|
|||
private static async Task<Application> CreateApplicationForSolutionAsync(OutputContext output, FileInfo solutionFile) |
|||
{ |
|||
// Solution workflow:
|
|||
//
|
|||
// 1. If there's an 'Opulence.csx' - use that that to initialize the set of services.
|
|||
// 2. If there's not an 'Opulence.csx' then grovel all of the projects in the solution looking
|
|||
// for executable projects.
|
|||
|
|||
SolutionFile solution; |
|||
try |
|||
{ |
|||
solution = SolutionFile.Parse(solutionFile.FullName); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
throw new CommandException($"Parsing solution file '{solutionFile.FullName}' failed.", ex); |
|||
} |
|||
|
|||
var application = await ScriptRunner.RunCustomizationScriptAsync(output, solutionFile, solution); |
|||
if (application != null) |
|||
{ |
|||
return application; |
|||
} |
|||
|
|||
return await InferApplicationForSolution(output, solutionFile, solution); |
|||
} |
|||
|
|||
private static async Task<Application> InferApplicationForSolution(OutputContext output, FileInfo solutionFile, SolutionFile solution) |
|||
{ |
|||
var globals = new ApplicationGlobals(); |
|||
|
|||
globals.Name = Names.NormalizeToDns(Path.GetFileNameWithoutExtension(solutionFile.Name)); |
|||
|
|||
var services = new List<ServiceEntry>(); |
|||
for (var i = 0; i < solution.ProjectsInOrder.Count; i++) |
|||
{ |
|||
// The library we're using doesn't translate Windows style paths automatically.
|
|||
var solutionProject = solution.ProjectsInOrder[i]; |
|||
if (solutionProject.AbsolutePath.EndsWith(".csproj", StringComparison.Ordinal)) |
|||
{ |
|||
var projectFilePath = solutionProject.RelativePath.Replace('\\', Path.DirectorySeparatorChar); |
|||
var projectFile = new FileInfo(projectFilePath); |
|||
|
|||
var name = Path.GetFileNameWithoutExtension(projectFile.Name); |
|||
var project = new Project(projectFile.FullName); |
|||
var service = new ServiceEntry(new Service(name), name); |
|||
service.Service.Source = project; |
|||
services.Add(service); |
|||
|
|||
await ProjectReader.ReadProjectDetailsAsync(output, projectFile, project); |
|||
|
|||
var container = new ContainerInfo(); |
|||
service.Service.GeneratedAssets.Container = container; |
|||
} |
|||
} |
|||
|
|||
var application = new GroveledApplication(globals, solutionFile.DirectoryName, services); |
|||
|
|||
foreach (var service in application.Services) |
|||
{ |
|||
DockerfileGenerator.ApplyContainerDefaults(application, service, (Project)service.Service.Source!, service.Service.GeneratedAssets.Container!); |
|||
} |
|||
|
|||
return application; |
|||
} |
|||
} |
|||
} |
|||
@ -1,59 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.CommandLine; |
|||
using System.CommandLine.Invocation; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
{ |
|||
internal static class GenerateCommand |
|||
{ |
|||
public static Command Create() |
|||
{ |
|||
var command = new Command("generate", "Generate assets") |
|||
{ |
|||
StandardOptions.Project, |
|||
StandardOptions.Verbosity, |
|||
StandardOptions.Outputs, |
|||
StandardOptions.Force, |
|||
}; |
|||
|
|||
command.Handler = CommandHandler.Create<IConsole, FileInfo, Verbosity, List<string>, bool>((console, project, verbosity, outputs, force) => |
|||
{ |
|||
var output = new OutputContext(console, verbosity); |
|||
return ExecuteAsync(output, project, outputs, force); |
|||
}); |
|||
|
|||
return command; |
|||
} |
|||
|
|||
private static async Task ExecuteAsync(OutputContext output, FileInfo projectFile, List<string> outputs, bool force) |
|||
{ |
|||
output.WriteBanner(); |
|||
|
|||
var application = await ApplicationFactory.CreateApplicationAsync(output, projectFile); |
|||
|
|||
var steps = new List<ServiceExecutor.Step>(); |
|||
|
|||
if (outputs.Count == 0 || outputs.Contains("container")) |
|||
{ |
|||
steps.Add(new GenerateDockerfileStep() { Force = force, }); |
|||
} |
|||
|
|||
if (outputs.Count == 0 || outputs.Contains("chart")) |
|||
{ |
|||
steps.Add(new GenerateHelmChartStep()); |
|||
} |
|||
|
|||
var executor = new ServiceExecutor(output, application, steps); |
|||
foreach (var service in application.Services) |
|||
{ |
|||
if (service.IsMatchForProject(application, projectFile)) |
|||
{ |
|||
await executor.ExecuteAsync(service); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,119 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.CommandLine; |
|||
using System.CommandLine.Invocation; |
|||
using System.IO; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
{ |
|||
public class PackageCommand |
|||
{ |
|||
public static Command Create() |
|||
{ |
|||
var command = new Command("package", "Package the project") |
|||
{ |
|||
StandardOptions.Project, |
|||
StandardOptions.Verbosity, |
|||
StandardOptions.Force, |
|||
StandardOptions.Environment, |
|||
new Option(new []{ "-o", "--output" }, "Output directory") |
|||
{ |
|||
Argument = new Argument<DirectoryInfo>("output", () => new DirectoryInfo(Environment.CurrentDirectory)) |
|||
{ |
|||
Arity = ArgumentArity.ExactlyOne, |
|||
}, |
|||
Required = false, |
|||
}, |
|||
}; |
|||
command.Handler = CommandHandler.Create<IConsole, FileInfo, DirectoryInfo, string, bool, Verbosity>((console, project, output, environment, force, verbosity) => |
|||
{ |
|||
return ExecuteAsync(new OutputContext(console, verbosity), project, output, environment, force); |
|||
}); |
|||
|
|||
return command; |
|||
} |
|||
|
|||
private static async Task ExecuteAsync(OutputContext output, FileInfo projectFile, DirectoryInfo outputDirectory, string environment, bool force) |
|||
{ |
|||
output.WriteBanner(); |
|||
|
|||
var application = await ApplicationFactory.CreateApplicationAsync(output, projectFile); |
|||
|
|||
var steps = new List<ServiceExecutor.Step> |
|||
{ |
|||
new CombineStep() { Environment = environment, }, |
|||
new BuildDockerImageStep() { Environment = environment, }, |
|||
}; |
|||
|
|||
if (application.Globals.DeploymentKind == DeploymentKind.None) |
|||
{ |
|||
// No extra steps
|
|||
} |
|||
else if (application.Globals.DeploymentKind == DeploymentKind.Kubernetes) |
|||
{ |
|||
steps.Add(new GenerateKubernetesManifestStep() { Environment = environment, }); |
|||
} |
|||
else if (application.Globals.DeploymentKind == DeploymentKind.Oam) |
|||
{ |
|||
steps.Add(new GenerateOamComponentStep() { Environment = environment, }); |
|||
} |
|||
else |
|||
{ |
|||
throw new InvalidOperationException($"Unknown DeploymentKind: " + application.Globals.DeploymentKind); |
|||
} |
|||
|
|||
// If this is command is for a project, then write out the component manifest
|
|||
// for just the project. We won't run the "application package" part.
|
|||
if (!string.Equals(".sln", projectFile.Extension, StringComparison.Ordinal)) |
|||
{ |
|||
steps.Add(new WriteServiceYamlStep() { OutputDirectory = outputDirectory, Force = force, }); |
|||
} |
|||
|
|||
var executor = new ServiceExecutor(output, application, steps); |
|||
foreach (var service in application.Services) |
|||
{ |
|||
if (service.IsMatchForProject(application, projectFile)) |
|||
{ |
|||
await executor.ExecuteAsync(service); |
|||
} |
|||
} |
|||
|
|||
if (string.Equals(".sln", projectFile.Extension, StringComparison.Ordinal)) |
|||
{ |
|||
await PackageApplicationAsync(output, application, outputDirectory, Path.GetFileNameWithoutExtension(projectFile.Name), environment); |
|||
} |
|||
} |
|||
|
|||
private static async Task PackageApplicationAsync(OutputContext output, Application application, DirectoryInfo outputDirectory, string applicationName, string environment) |
|||
{ |
|||
using var step = output.BeginStep("Writing Application Manifests..."); |
|||
var outputFile = Path.Combine(outputDirectory.FullName, $"{applicationName}-{environment}.yaml"); |
|||
output.WriteInfoLine($"Writing output to '{outputFile}'."); |
|||
|
|||
File.Delete(outputFile); |
|||
using var stream = File.OpenWrite(outputFile); |
|||
using var writer = new StreamWriter(stream, Encoding.UTF8, leaveOpen: true); |
|||
|
|||
if (application.Globals.DeploymentKind == DeploymentKind.None) |
|||
{ |
|||
// No extra steps
|
|||
} |
|||
else if (application.Globals.DeploymentKind == DeploymentKind.Kubernetes) |
|||
{ |
|||
await ApplicationYamlWriter.WriteAsync(output, writer, application); |
|||
} |
|||
else if (application.Globals.DeploymentKind == DeploymentKind.Oam) |
|||
{ |
|||
await OamApplicationGenerator.WriteOamApplicationAsync(writer, output, application, applicationName, environment); |
|||
} |
|||
else |
|||
{ |
|||
throw new InvalidOperationException($"Unknown DeploymentKind: " + application.Globals.DeploymentKind); |
|||
} |
|||
|
|||
step.MarkComplete(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,8 +0,0 @@ |
|||
{ |
|||
"profiles": { |
|||
"dotnet-opulence": { |
|||
"commandName": "Project", |
|||
"commandLineArgs": "" |
|||
} |
|||
} |
|||
} |
|||
@ -1,55 +0,0 @@ |
|||
using System; |
|||
using System.CommandLine; |
|||
using System.CommandLine.Invocation; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Opulence |
|||
{ |
|||
public class PushCommand |
|||
{ |
|||
public static Command Create() |
|||
{ |
|||
var command = new Command("push", "Push the application to registry") |
|||
{ |
|||
StandardOptions.Project, |
|||
StandardOptions.Verbosity, |
|||
StandardOptions.Environment, |
|||
}; |
|||
|
|||
command.Handler = CommandHandler.Create<IConsole, FileInfo, string, Verbosity>((console, project, environment, verbosity) => |
|||
{ |
|||
return ExecuteAsync(new OutputContext(console, verbosity), project, environment); |
|||
}); |
|||
|
|||
return command; |
|||
} |
|||
|
|||
private static async Task ExecuteAsync(OutputContext output, FileInfo projectFile, string environment) |
|||
{ |
|||
output.WriteBanner(); |
|||
|
|||
var application = await ApplicationFactory.CreateApplicationAsync(output, projectFile); |
|||
if (application.Globals.Registry?.Hostname == null) |
|||
{ |
|||
throw new CommandException("A registry is required for push operations. run 'dotnet-opulence init'."); |
|||
} |
|||
|
|||
var steps = new ServiceExecutor.Step[] |
|||
{ |
|||
new CombineStep() { Environment = environment, }, |
|||
new BuildDockerImageStep() { Environment = environment, }, |
|||
new PushDockerImageStep() { Environment = environment, }, |
|||
}; |
|||
|
|||
var executor = new ServiceExecutor(output, application, steps); |
|||
foreach (var service in application.Services) |
|||
{ |
|||
if (service.IsMatchForProject(application, projectFile)) |
|||
{ |
|||
await executor.ExecuteAsync(service); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,166 +0,0 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Build.Construction; |
|||
using Microsoft.CodeAnalysis.CSharp; |
|||
using Microsoft.CodeAnalysis.CSharp.Scripting; |
|||
using Microsoft.CodeAnalysis.Scripting; |
|||
|
|||
namespace Opulence |
|||
{ |
|||
internal static class ScriptRunner |
|||
{ |
|||
public static async Task<ApplicationWrapper?> RunCustomizationScriptAsync(OutputContext output, FileInfo projectFile) |
|||
{ |
|||
if (output is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(output)); |
|||
} |
|||
|
|||
using (var step = output.BeginStep("Applying Application Customizations...")) |
|||
{ |
|||
var scriptFilePath = DirectorySearch.AscendingSearch(projectFile.DirectoryName, "Opulence.csx"); |
|||
output.WriteDebugLine($"Looking for customization script above '{projectFile}'."); |
|||
if (!File.Exists(scriptFilePath)) |
|||
{ |
|||
output.WriteDebugLine($"No customization script found."); |
|||
step.MarkComplete("Skipping..."); |
|||
return null; |
|||
} |
|||
|
|||
output.WriteInfoLine($"Configuring application using '{Path.GetFileName(scriptFilePath)}'."); |
|||
|
|||
var code = File.ReadAllText(scriptFilePath); |
|||
var script = CSharpScript.Create<object>( |
|||
code, |
|||
options: ScriptOptions.Default.WithImports(new[] { "System", "System.Collections.Generic", }), |
|||
globalsType: typeof(PipelineHolder), |
|||
assemblyLoader: null); |
|||
script = script.ContinueWith<object>(@"return await Pipeline.ExecuteAsync(__Pipeline);", options: ScriptOptions.Default); |
|||
|
|||
output.WriteDebugLine($"Compiling {Path.GetFileName(scriptFilePath)}'."); |
|||
script.Compile(); |
|||
var diagnostics = script.Compile(); |
|||
if (diagnostics.Length > 0) |
|||
{ |
|||
var builder = new StringBuilder(); |
|||
output.WriteDebugLine($"Script '{scriptFilePath}' had compilation errors."); |
|||
builder.AppendLine($"Script '{scriptFilePath}' had compilation errors."); |
|||
foreach (var diagnostic in diagnostics) |
|||
{ |
|||
output.WriteDebugLine(CSharpDiagnosticFormatter.Instance.Format(diagnostic)); |
|||
builder.AppendLine(CSharpDiagnosticFormatter.Instance.Format(diagnostic)); |
|||
} |
|||
|
|||
throw new CommandException(builder.ToString()); |
|||
} |
|||
output.WriteDebugLine($"Done compiling {Path.GetFileName(scriptFilePath)}'."); |
|||
|
|||
var pipeline = new CustomizationPipeline( |
|||
output, |
|||
rootDirectory: Path.GetDirectoryName(scriptFilePath)!, |
|||
name: Names.NormalizeToDns(Path.GetFileNameWithoutExtension(projectFile.Name)), |
|||
solution: null, |
|||
projectFile); |
|||
var holder = new PipelineHolder(pipeline); |
|||
|
|||
output.WriteDebugLine($"Running {Path.GetFileName(scriptFilePath)}'."); |
|||
object obj; |
|||
try |
|||
{ |
|||
var result = await script.RunAsync(holder); |
|||
obj = result.ReturnValue; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
throw new CommandException($"Failed executing {Path.GetFileName(scriptFilePath)}'.", ex); |
|||
} |
|||
|
|||
step.MarkComplete(); |
|||
return new ApplicationWrapper(obj, Path.GetDirectoryName(scriptFilePath)!); |
|||
} |
|||
} |
|||
|
|||
public static async Task<ApplicationWrapper?> RunCustomizationScriptAsync(OutputContext output, FileInfo solutionFile, SolutionFile solution) |
|||
{ |
|||
if (output is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(output)); |
|||
} |
|||
|
|||
if (solutionFile is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(solutionFile)); |
|||
} |
|||
|
|||
if (solution is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(solution)); |
|||
} |
|||
|
|||
using (var step = output.BeginStep("Applying Application Customizations...")) |
|||
{ |
|||
var scriptFilePath = Path.Combine(solutionFile.DirectoryName, "Opulence.csx"); |
|||
output.WriteDebugLine($"Looking for customization script at '{scriptFilePath}'."); |
|||
if (!File.Exists(scriptFilePath)) |
|||
{ |
|||
output.WriteDebugLine($"No customization script found."); |
|||
step.MarkComplete("Skipping..."); |
|||
return null; |
|||
} |
|||
|
|||
output.WriteInfoLine($"Configuring application using '{Path.GetFileName(scriptFilePath)}'."); |
|||
|
|||
var code = File.ReadAllText(scriptFilePath); |
|||
var script = CSharpScript.Create<object>( |
|||
code, |
|||
options: ScriptOptions.Default.WithImports(new[] { "System", "System.Collections.Generic", }), |
|||
globalsType: typeof(PipelineHolder), |
|||
assemblyLoader: null); |
|||
script = script.ContinueWith<object>(@"return await Pipeline.ExecuteAsync(__Pipeline);", options: ScriptOptions.Default); |
|||
|
|||
output.WriteDebugLine($"Compiling {Path.GetFileName(scriptFilePath)}'."); |
|||
script.Compile(); |
|||
var diagnostics = script.Compile(); |
|||
if (diagnostics.Length > 0) |
|||
{ |
|||
var builder = new StringBuilder(); |
|||
output.WriteDebugLine($"Script '{scriptFilePath}' had compilation errors."); |
|||
builder.AppendLine($"Script '{scriptFilePath}' had compilation errors."); |
|||
foreach (var diagnostic in diagnostics) |
|||
{ |
|||
output.WriteDebugLine(CSharpDiagnosticFormatter.Instance.Format(diagnostic)); |
|||
builder.AppendLine(CSharpDiagnosticFormatter.Instance.Format(diagnostic)); |
|||
} |
|||
|
|||
throw new CommandException(builder.ToString()); |
|||
} |
|||
output.WriteDebugLine($"Done compiling {Path.GetFileName(scriptFilePath)}'."); |
|||
|
|||
var pipeline = new CustomizationPipeline( |
|||
output, |
|||
rootDirectory: Path.GetDirectoryName(scriptFilePath)!, |
|||
name: Names.NormalizeToDns(Path.GetFileNameWithoutExtension(solutionFile.Name)), |
|||
solution, |
|||
projectFile: null); |
|||
var holder = new PipelineHolder(pipeline); |
|||
|
|||
output.WriteDebugLine($"Running {Path.GetFileName(scriptFilePath)}'."); |
|||
object obj; |
|||
try |
|||
{ |
|||
var result = await script.RunAsync(holder); |
|||
obj = result.ReturnValue; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
throw new CommandException($"Failed executing {Path.GetFileName(scriptFilePath)}'.", ex); |
|||
} |
|||
|
|||
step.MarkComplete(); |
|||
return new ApplicationWrapper(obj, Path.GetDirectoryName(scriptFilePath)!); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<RootNamespace>Opulence</RootNamespace> |
|||
<PackAsTool>true</PackAsTool> |
|||
<PackageId>Opulence.dotnet-opulence</PackageId> |
|||
<ToolCommandName>opulence</ToolCommandName> |
|||
<Nullable>Enable</Nullable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="KubernetesClient" Version="1.6.11" /> |
|||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.4.0" /> |
|||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.4.0" /> |
|||
<PackageReference Include="semver" Version="2.0.6" /> |
|||
<PackageReference Include="Sln" Version="0.3.0" /> |
|||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20071.2" /> |
|||
<PackageReference Include="System.Commandline.Rendering" Version="0.3.0-alpha.20070.2" /> |
|||
<PackageReference Include="System.Reflection.Metadata" Version="1.8.0" /> |
|||
<PackageReference Include="YamlDotNet.Signed" Version="6.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Opulence\Opulence.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Content Include="build\**" CopyToOutputDirectory="PreserveNewest" /> |
|||
<Content Include="buildMultiTargeting\**" CopyToOutputDirectory="PreserveNewest" /> |
|||
<Content Include="Templates\**" CopyToOutputDirectory="PreserveNewest" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Include="..\..\tye\TempDirectory.cs" Link="TempDirectory.cs" /> |
|||
<Compile Include="..\..\tye\TempFile.cs" Link="TempFile.cs" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="Resources\Imports.targets" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
Loading…
Reference in new issue