/// <summary>
        /// Creates a target resource for the snippet.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="snippetKey">The key of the snippet.</param>
        /// <param name="snippetNode">The snippet from configuration.</param>
        /// <returns></returns>
        private TargetResourceSnippet CreateTargetResourceSnippet(AzureIntegrationServicesModel model, YamlScalarNode snippetKey, YamlMappingNode snippetNode)
        {
            // Mandatory fields
            var targetResource = new TargetResourceSnippet()
            {
                SnippetKey   = ((YamlScalarNode)snippetNode.Children["snippet"]).Value,
                SnippetType  = ((YamlScalarNode)snippetNode.Children["snippetType"]).Value,
                ResourceName = ((YamlScalarNode)snippetNode.Children["resourceName"]).Value,
                ResourceType = ((YamlScalarNode)snippetNode.Children["resourceType"]).Value
            };

            // Optional fields
            if (snippetNode.Children.ContainsKey("outputPath"))
            {
                targetResource.OutputPath = ((YamlScalarNode)snippetNode.Children["outputPath"]).Value;
            }

            // Parameters
            if (snippetNode.Children.ContainsKey("parameters"))
            {
                var templateParams = (YamlSequenceNode)snippetNode.Children["parameters"];
                if (templateParams != null)
                {
                    foreach (var param in templateParams)
                    {
                        var paramNode = ((YamlMappingNode)param).Children.SingleOrDefault();
                        targetResource.Parameters.Add(((YamlScalarNode)paramNode.Key).Value, ((YamlScalarNode)paramNode.Value).Value);
                    }
                }
            }

            // Files
            if (snippetNode.Children.ContainsKey("files"))
            {
                var snippetFiles = (YamlSequenceNode)snippetNode.Children["files"];
                if (snippetFiles != null)
                {
                    _logger.LogTrace(TraceMessages.FilteringSnippetsByEnvironment, model.MigrationTarget.DeploymentEnvironment, snippetKey.Value);

                    foreach (var snippetFileNode in snippetFiles)
                    {
                        var snippetFile = (YamlMappingNode)snippetFileNode;

                        // Filter by deployment environment
                        var envNameNode = (YamlSequenceNode)snippetFile.Children["env"];
                        var envNames    = envNameNode.Select(t => ((YamlScalarNode)t).Value.ToUpperInvariant());
                        if (envNames.Contains(model.MigrationTarget.DeploymentEnvironment.ToUpperInvariant()))
                        {
                            _logger.LogTrace(TraceMessages.FoundSnippetFileForEnvironment, model.MigrationTarget.DeploymentEnvironment, snippetKey.Value);

                            // Get path
                            targetResource.ResourceSnippetFile = ((YamlScalarNode)snippetFile.Children["path"]).Value;
                        }
                    }
                }
            }

            return(targetResource);
        }
Exemple #2
0
        public void RenderTemplateAsyncWithSnippetContentNullError(ISnippetRenderer renderer, AzureIntegrationServicesModel model, ProcessManager processManager, TargetResourceTemplate resourceTemplate, TargetResourceSnippet resourceSnippet, WorkflowObject workflowObject, string snippetContent, string renderedContent, Exception e)
        {
            "Given a snippet renderer"
            .x(() => renderer = new LiquidSnippetRenderer(_mockLogger.Object));

            "And a model"
            .x(() => model = _model);

            "And a process manager"
            .x(() =>
            {
                var messagingObject = model.FindMessagingObject("ContosoMessageBus:AppA:FtpTransformWorkflow");
                messagingObject.messagingObject.Should().NotBeNull().And.BeOfType(typeof(ProcessManager));
                processManager   = (ProcessManager)messagingObject.messagingObject;
                resourceTemplate = processManager.Resources.First();
                resourceSnippet  = processManager.Snippets.First();
            });

            "And a workflow object"
            .x(() =>
            {
                workflowObject = processManager.WorkflowModel.Activities.First();
            });

            "And null snippet content"
            .x(() => snippetContent = null);

            "When rendering the template"
            .x(async() => e = await Record.ExceptionAsync(async() => renderedContent = await renderer.RenderSnippetAsync(snippetContent, model, processManager, resourceTemplate, resourceSnippet, workflowObject)));

            "Then the render should error"
            .x(() => e.Should().NotBeNull().And.Subject.Should().BeOfType <ArgumentNullException>().Which.ParamName.Should().Be("snippetContent"));

            "And the rendered content should not have a value"
            .x(() => renderedContent.Should().BeNull());
        }
Exemple #3
0
        public void RenderSnippetAsyncWithMissingMessagingObjectWithWarning(ISnippetRenderer renderer, AzureIntegrationServicesModel model, ProcessManager processManager, ProcessManager missingProcessManager, TargetResourceTemplate resourceTemplate, TargetResourceSnippet resourceSnippet, WorkflowObject workflowObject, string snippetContent, string renderedContent, Exception e)
        {
            "Given a snippet renderer"
            .x(() => renderer = new LiquidSnippetRenderer(_mockLogger.Object));

            "And a model"
            .x(() => model = _model);

            "And a missing process manager"
            .x(() =>
            {
                missingProcessManager = new ProcessManager("MissingProcessManager")
                {
                    Key = "MissingProcessManager"
                };
            });

            "And a workflow object"
            .x(() =>
            {
                var messagingObject = model.FindMessagingObject("ContosoMessageBus:AppA:FtpTransformWorkflow");
                messagingObject.messagingObject.Should().NotBeNull().And.BeOfType(typeof(ProcessManager));
                processManager   = (ProcessManager)messagingObject.messagingObject;
                resourceTemplate = processManager.Resources.First();
                resourceSnippet  = processManager.Snippets.First();
                workflowObject   = processManager.WorkflowModel.Activities.First();
            });

            "And a snippet content"
            .x(() => snippetContent = _missingProcessManagerSnippet);

            "When rendering the snippet"
            .x(async() => e = await Record.ExceptionAsync(async() => renderedContent = await renderer.RenderSnippetAsync(snippetContent, model, missingProcessManager, resourceTemplate, resourceSnippet, workflowObject)));

            "Then the render should succeed"
            .x(() => e.Should().BeNull());

            "And the rendered content should not have expected values from the model"
            .x(() =>
            {
                renderedContent.Should().NotBeNull().And.Be("").And.NotContainAny("{{").And.NotContainAny("}}");

                // Verify warning was raised
                _mockLogger.Verify(l => l.Log(
                                       It.Is <LogLevel>(l => l == LogLevel.Warning),
                                       It.IsAny <EventId>(),
                                       It.Is <It.IsAnyType>((v, t) => v.ToString().Contains("does not appear in the target model", StringComparison.CurrentCultureIgnoreCase)),
                                       It.IsAny <Exception>(),
                                       It.Is <Func <It.IsAnyType, Exception, string> >((v, t) => true)), Times.Once);
            });
        }
Exemple #4
0
        public void RenderSnippetAsyncWithSuccess(ISnippetRenderer renderer, AzureIntegrationServicesModel model, ProcessManager processManager, TargetResourceTemplate resourceTemplate, TargetResourceSnippet resourceSnippet, WorkflowObject workflowObject, string snippetContent, string renderedContent, Exception e)
        {
            "Given a snippet renderer"
            .x(() => renderer = new LiquidSnippetRenderer(_mockLogger.Object));

            "And a model"
            .x(() => model = _model);

            "And a process manager"
            .x(() =>
            {
                var messagingObject = model.FindMessagingObject("ContosoMessageBus:AppA:FtpTransformWorkflow");
                messagingObject.messagingObject.Should().NotBeNull().And.BeOfType(typeof(ProcessManager));
                processManager   = (ProcessManager)messagingObject.messagingObject;
                resourceTemplate = processManager.Resources.First();
                resourceSnippet  = processManager.Snippets.First();
            });

            "And a workflow object"
            .x(() =>
            {
                workflowObject = processManager.WorkflowModel.Activities.First();
            });

            "And a snippet content"
            .x(() => snippetContent = _snippetContent);

            "When rendering the snippet"
            .x(async() => e = await Record.ExceptionAsync(async() => renderedContent = await renderer.RenderSnippetAsync(snippetContent, model, processManager, resourceTemplate, resourceSnippet, workflowObject)));

            "Then the render should succeed"
            .x(() => e.Should().BeNull());

            "And the rendered content should have expected values from the model"
            .x(() =>
            {
                renderedContent.Should().NotBeNull().And.ContainAny($"StepName:_{workflowObject.Name.Replace(" ", "_", StringComparison.InvariantCulture)}").And.NotContainAny("{{").And.NotContainAny("}}");
            });
        }
Exemple #5
0
        /// <summary>
        /// Renders a snippet using a Liquid template engine.
        /// </summary>
        /// <param name="snippetContent">The snippet content to render.</param>
        /// <param name="model">The model used to provide properties to snippet Liquid templates.</param>
        /// <param name="messagingObject">An optional messaging object to add to the variable context, accessible to snippets.</param>
        /// <param name="resourceTemplate">An optional resource template object to add to the variable context, accessible to templates.</param>
        /// <param name="resourceSnippet">An optional resource template object to add to the variable context, accessible to snippets.</param>
        /// <param name="workflowObject">A workflow object to add to the variable context, accessible to snippets.</param>
        /// <returns>The rendered snippet content.</returns>
        public async Task <string> RenderSnippetAsync(string snippetContent, AzureIntegrationServicesModel model, MessagingObject messagingObject = null, TargetResourceTemplate resourceTemplate = null, TargetResourceSnippet resourceSnippet = null, WorkflowObject workflowObject = null)
        {
            _ = model ?? throw new ArgumentNullException(nameof(model));
            _ = snippetContent ?? throw new ArgumentNullException(nameof(snippetContent));

            // Create variables on script object, to be accessible to Liquid templates
            var scriptObject = new ScriptObject
            {
                ["model"] = model
            };

            // Is there a messaging object?
            if (messagingObject != null)
            {
                var messagingObjects = model.FindMessagingObject(messagingObject.Key);
                if (messagingObjects.messageBus != null)
                {
                    scriptObject["message_bus"] = messagingObjects.messageBus;

                    if (messagingObjects.application != null)
                    {
                        scriptObject["application"] = messagingObjects.application;
                    }

                    if (messagingObjects.messagingObject != null)
                    {
                        scriptObject["messaging_object"] = messagingObjects.messagingObject;

                        switch (messagingObjects.messagingObject.Type)
                        {
                        case MessagingObjectType.Message:
                            scriptObject["message"] = (Message)messagingObjects.messagingObject;
                            break;

                        case MessagingObjectType.Channel:
                            scriptObject["channel"] = (Channel)messagingObjects.messagingObject;
                            break;

                        case MessagingObjectType.Intermediary:
                            scriptObject["intermediary"] = (Intermediary)messagingObjects.messagingObject;
                            break;

                        case MessagingObjectType.Endpoint:
                            scriptObject["endpoint"] = (Endpoint)messagingObjects.messagingObject;
                            break;
                        }
                    }
                }
                else
                {
                    // Should never happen, unless the messaging object is not attached to the target model
                    _logger.LogWarning(WarningMessages.MessagingObjectMissingInModel, messagingObject.Key);
                }
            }

            // Is there a resource template?
            if (resourceTemplate != null)
            {
                scriptObject["resource_template"] = resourceTemplate;
            }

            // Is there a resource snippet?
            if (resourceSnippet != null)
            {
                scriptObject["resource_snippet"] = resourceSnippet;
            }

            // Is there a workflow object?
            if (workflowObject != null)
            {
                scriptObject["workflow_object"] = workflowObject;
            }

            // Push variables onto the context
            _context.PushGlobal(scriptObject);

            try
            {
                // Render snippet
                var snippet         = Template.ParseLiquid(snippetContent);
                var renderedContent = await snippet.RenderAsync(_context).ConfigureAwait(false);

                return(renderedContent);
            }
            finally
            {
                // Pop model from context stack
                _context.PopGlobal();
            }
        }