public static async Task <ApplicationBuilder> CreateAsync(OutputContext output, FileInfo source) { if (source is null) { throw new ArgumentNullException(nameof(source)); } var config = ConfigFactory.FromFile(source); ValidateConfigApplication(config); var builder = new ApplicationBuilder(source, config.Name ?? source.Directory.Name.ToLowerInvariant()); if (!string.IsNullOrEmpty(config.Registry)) { builder.Registry = new ContainerRegistry(config.Registry); } foreach (var configService in config.Services) { ServiceBuilder service; if (!string.IsNullOrEmpty(configService.Project)) { var expandedProject = Environment.ExpandEnvironmentVariables(configService.Project); var projectFile = new FileInfo(Path.Combine(builder.Source.DirectoryName, expandedProject)); var project = new ProjectServiceBuilder(configService.Name, projectFile); service = project; project.Build = configService.Build ?? true; project.Args = configService.Args; project.Replicas = configService.Replicas ?? 1; await ProjectReader.ReadProjectDetailsAsync(output, project); // We don't apply more container defaults here because we might need // to prompty for the registry name. project.ContainerInfo = new ContainerInfo() { UseMultiphaseDockerfile = false, }; } else if (!string.IsNullOrEmpty(configService.Image)) { var container = new ContainerServiceBuilder(configService.Name, configService.Image) { Args = configService.Args, Replicas = configService.Replicas ?? 1 }; service = container; } else if (!string.IsNullOrEmpty(configService.Executable)) { var expandedExecutable = Environment.ExpandEnvironmentVariables(configService.Executable); var workingDirectory = ""; // Special handling of .dlls as executables (it will be executed as dotnet {dll}) if (Path.GetExtension(expandedExecutable) == ".dll") { expandedExecutable = Path.GetFullPath(Path.Combine(builder.Source.Directory.FullName, expandedExecutable)); workingDirectory = Path.GetDirectoryName(expandedExecutable) !; } var executable = new ExecutableServiceBuilder(configService.Name, expandedExecutable) { Args = configService.Args, WorkingDirectory = configService.WorkingDirectory != null? Path.GetFullPath(Path.Combine(builder.Source.Directory.FullName, Environment.ExpandEnvironmentVariables(configService.WorkingDirectory))) : workingDirectory, Replicas = configService.Replicas ?? 1 }; service = executable; } else if (configService.External) { var external = new ExternalServiceBuilder(configService.Name); service = external; } else { throw new CommandException("Unable to determine service type."); } builder.Services.Add(service); // If there are no bindings and we're in ASP.NET Core project then add an HTTP and HTTPS binding if (configService.Bindings.Count == 0 && service is ProjectServiceBuilder project2 && project2.Frameworks.Any(f => f.Name == "Microsoft.AspNetCore.App")) { // HTTP is the default binding service.Bindings.Add(new BindingBuilder() { AutoAssignPort = true, Protocol = "http" }); service.Bindings.Add(new BindingBuilder() { Name = "https", AutoAssignPort = true, Protocol = "https" }); }
public static async Task <ApplicationBuilder> CreateAsync(OutputContext output, FileInfo source) { if (source is null) { throw new ArgumentNullException(nameof(source)); } var config = ConfigFactory.FromFile(source); ValidateConfigApplication(config); var builder = new ApplicationBuilder(source, config.Name ?? source.Directory.Name.ToLowerInvariant()); if (!string.IsNullOrEmpty(config.Registry)) { builder.Registry = new ContainerRegistry(config.Registry); } foreach (var configService in config.Services) { ServiceBuilder service; if (!string.IsNullOrEmpty(configService.Project)) { var expandedProject = Environment.ExpandEnvironmentVariables(configService.Project); var projectFile = new FileInfo(Path.Combine(builder.Source.DirectoryName, expandedProject)); var project = new ProjectServiceBuilder(configService.Name, projectFile); service = project; project.Build = configService.Build ?? true; project.Args = configService.Args; project.Replicas = configService.Replicas ?? 1; await ProjectReader.ReadProjectDetailsAsync(output, project); // We don't apply more container defaults here because we might need // to prompty for the registry name. project.ContainerInfo = new ContainerInfo() { UseMultiphaseDockerfile = false, }; } else if (!string.IsNullOrEmpty(configService.Image)) { var container = new ContainerServiceBuilder(configService.Name, configService.Image) { Args = configService.Args, Replicas = configService.Replicas ?? 1 }; service = container; } else if (!string.IsNullOrEmpty(configService.Executable)) { var expandedExecutable = Environment.ExpandEnvironmentVariables(configService.Executable); var workingDirectory = ""; // Special handling of .dlls as executables (it will be executed as dotnet {dll}) if (Path.GetExtension(expandedExecutable) == ".dll") { expandedExecutable = Path.GetFullPath(Path.Combine(builder.Source.Directory.FullName, expandedExecutable)); workingDirectory = Path.GetDirectoryName(expandedExecutable) !; } var executable = new ExecutableServiceBuilder(configService.Name, expandedExecutable) { Args = configService.Args, WorkingDirectory = configService.WorkingDirectory != null? Path.GetFullPath(Path.Combine(builder.Source.Directory.FullName, Environment.ExpandEnvironmentVariables(configService.WorkingDirectory))) : workingDirectory, Replicas = configService.Replicas ?? 1 }; service = executable; } else if (configService.External) { var external = new ExternalServiceBuilder(configService.Name); service = external; } else { throw new CommandException("Unable to determine service type."); } builder.Services.Add(service); foreach (var configBinding in configService.Bindings) { var binding = new BindingBuilder() { Name = configBinding.Name, AutoAssignPort = configBinding.AutoAssignPort, ConnectionString = configBinding.ConnectionString, Host = configBinding.Host, ContainerPort = configBinding.ContainerPort, Port = configBinding.Port, Protocol = configBinding.Protocol, }; // Assume HTTP for projects only (containers may be different) if (binding.ConnectionString == null && configService.Project != null) { binding.Protocol ??= "http"; } service.Bindings.Add(binding); } foreach (var configEnvVar in configService.Configuration) { var envVar = new EnvironmentVariable(configEnvVar.Name, configEnvVar.Value); if (service is ProjectServiceBuilder project) { project.EnvironmentVariables.Add(envVar); } else if (service is ContainerServiceBuilder container) { container.EnvironmentVariables.Add(envVar); } else if (service is ExecutableServiceBuilder executable) { executable.EnvironmentVariables.Add(envVar); } else if (service is ExternalServiceBuilder) { throw new CommandException("External services do not support environment variables."); } else { throw new CommandException("Unable to determine service type."); } } foreach (var configVolume in configService.Volumes) { var volume = new VolumeBuilder(configVolume.Source, configVolume.Target); if (service is ProjectServiceBuilder project) { project.Volumes.Add(volume); } else if (service is ContainerServiceBuilder container) { container.Volumes.Add(volume); } else if (service is ExecutableServiceBuilder executable) { throw new CommandException("Executable services do not support volumes."); } else if (service is ExternalServiceBuilder) { throw new CommandException("External services do not support volumes."); } else { throw new CommandException("Unable to determine service type."); } } } foreach (var configIngress in config.Ingress) { var ingress = new IngressBuilder(configIngress.Name); ingress.Replicas = configIngress.Replicas ?? 1; builder.Ingress.Add(ingress); foreach (var configBinding in configIngress.Bindings) { var binding = new IngressBindingBuilder() { AutoAssignPort = configBinding.AutoAssignPort, Name = configBinding.Name, Port = configBinding.Port, Protocol = configBinding.Protocol ?? "http", }; ingress.Bindings.Add(binding); } foreach (var configRule in configIngress.Rules) { var rule = new IngressRuleBuilder() { Host = configRule.Host, Path = configRule.Path, Service = configRule.Service, }; ingress.Rules.Add(rule); } } return(builder); }