Example #1
0
        public async Task <int> ExecuteCore(bool generateOnly)
        {
            if (!OutputDirectory.HasValue())
            {
                OutputDirectory.TryParse($"_output");
            }

            var logsPath = Path.Combine(OutputDirectory.Required(), "logs");

            if (Directory.Exists(logsPath))
            {
                foreach (var file in Directory.EnumerateFiles(logsPath))
                {
                    File.Delete(file);
                }
            }

            var blueprint = _blueprintManager.GetBlueprintPackage(Blueprint.Required());

            if (blueprint == null)
            {
                throw new ApplicationException($"Unable to locate blueprint {Blueprint.Required()}");
            }

            var templateEngine = _templateEngineFactory.Create(new TemplateEngineOptions
            {
                FileSystem = new BlueprintPackageFileSystem(blueprint)
            });

            var eachValues = new List <object>();

            if (blueprint.Exists("values.yaml"))
            {
                using (var reader = blueprint.OpenText("values.yaml"))
                {
                    eachValues.Add(_serializers.YamlDeserializer.Deserialize(reader));
                }
            }

            var defaultValuesFiles =
                File.Exists("atlas-values.yaml") ? new[] { "atlas-values.yaml" } :
            File.Exists("values.yaml") ? new[] { "values.yaml" } :
            new string[0];

            foreach (var valuesFile in Values.OptionalMany(defaultValuesFiles))
            {
                using (var reader = File.OpenText(valuesFile))
                {
                    eachValues.Add(_serializers.YamlDeserializer.Deserialize(reader));
                }
            }

            if (Set.HasValue())
            {
                var setValues = new Dictionary <object, object>();

                foreach (var set in Set.Values)
                {
                    var parts = set.Split('=', 2);
                    if (parts.Length == 1)
                    {
                        throw new ApplicationException("Equal sign required when using the option --set name=value");
                    }

                    var name     = parts[0];
                    var value    = parts[1];
                    var segments = name.Split('.');
                    if (segments.Any(segment => string.IsNullOrEmpty(segment)))
                    {
                        throw new ApplicationException("Name must not have empty segments when using the option --set name=value");
                    }

                    var cursor = (IDictionary <object, object>)setValues;
                    foreach (var segment in segments.Reverse().Skip(1).Reverse())
                    {
                        if (cursor.TryGetValue(segment, out var child) && child is IDictionary <object, object> )
                        {
                            cursor = (IDictionary <object, object>)child;
                        }
                        else
                        {
                            child           = new Dictionary <object, object>();
                            cursor[segment] = child;
                            cursor          = (IDictionary <object, object>)child;
                        }
                    }

                    cursor[segments.Last()] = value;
                }

                eachValues.Add(setValues);
            }

            IDictionary <object, object> values = new Dictionary <object, object>();

            foreach (var addValues in eachValues)
            {
                values = (IDictionary <object, object>)MergeUtils.Merge(addValues, values) ?? values;
            }

            object model;

            var modelTemplate = "model.yaml";
            var modelExists   = blueprint.Exists(modelTemplate);

            if (modelExists)
            {
                model = templateEngine.Render <object>(modelTemplate, values);
            }
            else
            {
                model = values;
            }

            var workflowTemplate = "workflow.yaml";
            var workflowContents = new StringBuilder();

            using (var workflowWriter = new StringWriter(workflowContents))
            {
                templateEngine.Render(workflowTemplate, model, workflowWriter);
            }

            // NOTE: the workflow is rendered BEFORE writing these output files because it may contain
            // calls to the "secret" helper which will redact tokens that might have been provided in values

            // write values to output folder
            GenerateOutput("values.yaml", writer => _serializers.YamlSerializer.Serialize(writer, values));

            if (modelExists)
            {
                // write normalized values to output folder
                GenerateOutput(modelTemplate, writer => templateEngine.Render(modelTemplate, values, writer));
            }

            // write workflow to output folder
            GenerateOutput("workflow.yaml", writer => writer.Write(workflowContents.ToString()));

            var workflow = _serializers.YamlDeserializer.Deserialize <WorkflowModel>(new StringReader(workflowContents.ToString()));

            var patternMatcher = _patternMatcherFactory.Create(Target.Values.Any() ? Target.Values : new List <string>()
            {
                "/**"
            });

            if (generateOnly == false)
            {
                var context = new ExecutionContext(templateEngine, patternMatcher, null);
                context.AddValuesIn(ProcessValues(workflow.values, context.Values));

                var resultOut = await ExecuteOperations(context, workflow.operations);

                if (workflow.output != null)
                {
                    context.AddValuesOut(ProcessValues(workflow.output, MergeUtils.Merge(resultOut, context.Values) ?? context.Values));
                }
                else
                {
                    context.AddValuesOut(resultOut);
                }

                if (context.ValuesOut != null)
                {
                    GenerateOutput("output.yaml", writer => _serializers.YamlSerializer.Serialize(writer, context.ValuesOut));

                    using (var writer = _secretTracker.FilterTextWriter(_console.Out))
                    {
                        _serializers.YamlSerializer.Serialize(writer, context.ValuesOut);
                    }
                }
            }

            return(0);
        }
Example #2
0
        public (ITemplateEngine templateEngine, WorkflowModel workflow, object effectiveValues) Load(IBlueprintPackage blueprint, object values, Action <string, Action <TextWriter> > generateOutput)
        {
            var templateEngine = _templateEngineFactory.Create(new TemplateEngineOptions
            {
                FileSystem = new BlueprintPackageFileSystem(blueprint)
            });

            var providedValues = values;

            if (blueprint.Exists("values.yaml"))
            {
                using (var reader = blueprint.OpenText("values.yaml"))
                {
                    var defaultValues = _serializers.YamlDeserializer.Deserialize(reader);
                    if (values == null)
                    {
                        values = defaultValues;
                    }
                    else
                    {
                        values = MergeUtils.Merge(values, defaultValues);
                    }
                }
            }

            var premodelValues = values;

            if (blueprint.Exists("model.yaml"))
            {
                var model = templateEngine.Render <object>("model.yaml", values);
                if (model != null)
                {
                    values = MergeUtils.Merge(model, values);
                }
            }

            var workflowContents = new StringBuilder();

            using (var workflowWriter = new StringWriter(workflowContents))
            {
                templateEngine.Render("workflow.yaml", values, workflowWriter);
            }

            // NOTE: the workflow is rendered BEFORE writing these output files because it may contain
            // calls to the "secret" helper which will redact tokens that might have been provided in values

            // write values to output folder
            generateOutput("values.yaml", writer => _serializers.YamlSerializer.Serialize(writer, values));

            // write workflow to output folder
            generateOutput("workflow.yaml", writer => writer.Write(workflowContents.ToString()));

            var workflow = _serializers.YamlDeserializer.Deserialize <WorkflowModel>(new StringReader(workflowContents.ToString()));

            foreach (var generatedFile in blueprint.GetGeneratedPaths())
            {
                using (var generatedContent = blueprint.OpenText(generatedFile))
                {
                    generateOutput($"generated/{generatedFile}", writer => writer.Write(generatedContent.ReadToEnd()));
                }
            }

            return(templateEngine, workflow, values);
        }