public static Task WriteOamApplicationAsync(TextWriter writer, OutputContext output, Application application, string applicationName, string environment) { if (writer is null) { throw new ArgumentNullException(nameof(writer)); } if (output is null) { throw new ArgumentNullException(nameof(output)); } if (application is null) { throw new ArgumentNullException(nameof(application)); } if (applicationName is null) { throw new ArgumentNullException(nameof(applicationName)); } if (environment is null) { throw new ArgumentNullException(nameof(environment)); } var componentManifests = new List <OamComponentOutput>(); var documents = new List <YamlDocument>(); foreach (var service in application.Services) { if (service.AppliesToEnvironment(environment)) { componentManifests.AddRange(service.Outputs.OfType <OamComponentOutput>()); } } var root = new YamlMappingNode(); root.Add("kind", "ApplicationConfiguration"); root.Add("apiVersion", "core.oam.dev/v1alpha1"); var metadata = new YamlMappingNode(); root.Add("metadata", metadata); metadata.Add("name", applicationName.ToLowerInvariant()); var spec = new YamlMappingNode(); root.Add("spec", spec); var components = new YamlSequenceNode(); spec.Add("components", components); foreach (var manifest in componentManifests) { documents.Add(manifest.Yaml); var component = new YamlMappingNode(); components.Add(component); component.Add("componentName", manifest.Name); component.Add("instanceName", $"{environment.ToLowerInvariant()}-{manifest.Name}"); } documents.Add(new YamlDocument(root)); var stream = new YamlStream(documents.ToArray()); stream.Save(writer, assignAnchors: false); return(Task.CompletedTask); }
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 deploy operations. run 'dotnet-opulence init'."); } var steps = new List <ServiceExecutor.Step>() { new CombineStep() { Environment = environment, }, new BuildDockerImageStep() { Environment = environment, }, new PushDockerImageStep() { 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 deploy the component manifest // for just the project. We won't run the "application deploy" part. if (!string.Equals(".sln", projectFile.Extension, StringComparison.Ordinal)) { steps.Add(new DeployServiceYamlStep() { Environment = environment, }); } 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, Path.GetFileNameWithoutExtension(projectFile.Name), environment); } }
private static async Task ExecuteAsync(OutputContext output, FileInfo projectFile, List <string> outputs, bool force) { var config = await OpulenceConfigFactory.ReadConfigAsync(output, projectFile.DirectoryName); if (config == null) { // Allow operating without config for now. output.WriteInfoLine("config was not found, using defaults"); config = new OpulenceConfig() { Container = new ContainerConfig() { Registry = new RegistryConfig(), } }; } var application = ApplicationFactory.CreateDefault(config, projectFile); await ProjectReader.InitializeAsync(output, application); await ScriptRunner.RunProjectScriptAsync(output, application); for (var i = 0; i < application.Steps.Count; i++) { var step = application.Steps[i]; if (step is ContainerStep container) { if (!outputs.Contains("container")) { // We should still apply the defaults here because they'll be used by // the helm step. DockerfileGenerator.ApplyContainerDefaults(application, container); output.WriteDebugLine("skipping container"); continue; } output.WriteInfoLine("generating dockerfile"); var dockerFilePath = Path.Combine(application.ProjectDirectory, "Dockerfile"); if (File.Exists(dockerFilePath) && !force) { throw new CommandException("'Dockerfile' already exists for project. use --force to overwrite"); } // force multi-phase dockerfile - this makes much more sense in the workflow // where you're going to maintain the dockerfile yourself. container.UseMultiphaseDockerfile = true; File.Delete(dockerFilePath); await DockerfileGenerator.WriteDockerfileAsync(output, application, container, dockerFilePath); } else if (step is HelmChartStep chart) { if (!outputs.Contains("chart")) { output.WriteDebugLine("skipping helm chart"); continue; } output.WriteInfoLine("generating helm charts"); var chartDirectory = Path.Combine(application.ProjectDirectory, "charts"); if (Directory.Exists(chartDirectory) && !force) { throw new CommandException("'charts' directory already exists for project. use --force to overwrite"); } await HelmChartGenerator.GenerateAsync( output, application, application.Steps.Get <ContainerStep>() !, chart, new DirectoryInfo(chartDirectory)); } } }