/// <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); }
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()); }
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); }); }
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("}}"); }); }
/// <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(); } }