/// <summary> /// CALLED FROM INVOKER. Run the activity in the provided context. Used to execute an activity within a workflow. If this activity metadata has not been added to the context it /// will be done now. /// </summary> /// <returns>True if completed, false if bookmarked.</returns> public bool RunInContext(IRunState runState, ActivityInputs inputs) { return(Execute(runState, inputs)); }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var OriginKey = GetArgumentKey("setRelationshipActivityOriginArgument"); var DestinationKey = GetArgumentKey("setRelationshipActivityDestinationArgument"); var RelationshipKey = GetArgumentKey("setRelationshipActivityRelationshipArgument"); var replaceExistingKey = GetArgumentKey("setRelationshipActivityReplaceExisting"); var isReverseKey = GetArgumentKey("setRelationshipActivityIsReverse"); var originRef = (IEntity)inputs[OriginKey]; var relationshipRef = (IEntity)inputs[RelationshipKey]; IEntity destinationRef = null; object destinationRefObj; if (inputs.TryGetValue(DestinationKey, out destinationRefObj)) { destinationRef = (IEntity)destinationRefObj; } bool replaceExisting = false; object replaceExistingObj; if (inputs.TryGetValue(replaceExistingKey, out replaceExistingObj)) { replaceExisting = (bool?)replaceExistingObj ?? false; } var direction = Direction.Forward; object isReverseObj; if (inputs.TryGetValue(isReverseKey, out isReverseObj)) { direction = ((bool?)isReverseObj ?? false) ? Direction.Reverse : Direction.Forward; } var relationship = relationshipRef.As <Relationship>(); SecurityBypassContext.RunAsUser(() => { var origin = originRef.AsWritable <Entity>(); var cardinality = relationship.Cardinality_Enum ?? CardinalityEnum_Enumeration.ManyToMany; replaceExisting = replaceExisting || cardinality == CardinalityEnum_Enumeration.OneToOne || (direction == Direction.Forward && cardinality == CardinalityEnum_Enumeration.ManyToOne) || (direction == Direction.Reverse && cardinality == CardinalityEnum_Enumeration.OneToMany) ; var relCollection = origin.GetRelationships(relationshipRef, direction); if (replaceExisting) { relCollection.Clear(); } if (destinationRef != null) { relCollection.Add(destinationRef); } origin.Save(); }); }
private const decimal DefaultTimeOutMins = 0; // no time out public override bool OnStart(IRunState context, ActivityInputs inputs) { var assignedTo = GetArgumentEntity <Person>(inputs, "inDisplayFormForUser"); var recordToPresent = GetArgumentEntity <UserResource>(inputs, "inDisplayFormResource"); var form = GetArgumentEntity <CustomEditForm>(inputs, "inDisplayFormForm"); var timeoutDays = GetArgumentValue <decimal>(inputs, "inDisplayFormTimeOut", DefaultTimeOutMins); var priority = GetArgumentEntity <EventEmailPriorityEnum>(inputs, "inDisplayFormPriority"); var activityInstanceAs = ActivityInstance.Cast <DisplayFormActivity>(); var percentageCompleted = GetArgumentValue <decimal?>(inputs, "inDisplayFormPercentageCompleted", null); var waitForNext = GetArgumentValue <bool>(inputs, "inDisplayFormWaitForNext", false); var recordHistory = GetArgumentValue <bool>(inputs, "inDisplayFormRecordHistory", false); var hideComment = GetArgumentValue <bool>(inputs, "inHideComment", false); var openInEditMode = GetArgumentValue <bool>(inputs, "inOpenInEditMode", false); priority = priority ?? Entity.Get <EventEmailPriorityEnum>(new EntityRef("core", "normalPriority")); var workflowRun = context.WorkflowRun; var dueDate = DateTime.UtcNow.AddDays((double)timeoutDays); var userTask = new DisplayFormUserTask { Name = ActivityInstance.Name ?? DefaultTitle, RecordToPresent = recordToPresent, FormToUse = form, AvailableTransitions = GetAvailableUserTransitions(), AssignedToUser = assignedTo, TaskPriority = priority, TaskStatus_Enum = TaskStatusEnum_Enumeration.TaskStatusNotStarted, PercentageCompleted = percentageCompleted, WaitForNextTask = waitForNext, UserTaskDueOn = dueDate, HideComment = hideComment, OpenInEditMode = openInEditMode, DfutLinkToken = CryptoHelper.GetRandomPrintableString(8) }; context.SetUserTask(userTask.Cast <BaseUserTask>()); if (recordHistory) { CreateLogEntry(context, userTask); } SetTimeoutIfNeeded(context, timeoutDays); var tenantSetting = Entity.Get <TenantGeneralSettings>(WellKnownAliases.CurrentTenant.TenantGeneralSettingsInstance); if (Factory.FeatureSwitch.Get("enableWfUserActionNotify")) { // // IN PROGRESS - Please leave // This code is in development and switched off until email and SMS approvals are required by PM. // Notifier notifier = null; // tenantSetting.UserActionNotifier; if (notifier != null) { // TODO: Format correctly for where it is being sent SMS email etc. Move the decision out of here and make the notfier decide on the type of message var generator = new HtmlGenerator(); string message = null; if (notifier.Is <EmailNotifier>()) // TODO: This is wrong, it should be somehow tied to the Router { var transitionOptions = userTask.AvailableTransitions.Select(t => t.FromExitPoint.Name).Where(n => !String.IsNullOrEmpty(n)); if (transitionOptions.Any()) { message = generator.GenerateSelectionPage(userTask); } } else if (notifier.Is <TwilioNotifier>()) { message = generator.GenerateSelectionPageUrl(userTask.DfutLinkToken); } if (message != null) { var userList = userTask.AssignedToUser.ToEnumerable(); var notification = new Notification { NMessage = message }; //TOOD: Add alternative text in the email with a link to the SMS page NotificationRouter.Instance.Send(notifier, notification, userList, false); } } } context.SetArgValue(ActivityInstance, GetArgumentKey("core:outDisplayFormUserTask"), userTask); context.SetArgValue(ActivityInstance, GetArgumentKey("core:dfaInternalKeepHistory"), recordHistory); return(false); }
/// <summary> /// Builds a request from the current state of the workflow run to initiate the appropriate action remotely. /// </summary> /// <param name="context">The workflow run context.</param> /// <param name="inputs">The activity input arguments.</param> /// <returns>The request object.</returns> protected abstract TRequest GetRequest(IRunState context, ActivityInputs inputs);
/// <summary> /// Keep running outstanding activities until completion. /// </summary> /// <returns>True, workflow has completed, False if there are pending activities.</returns> bool RunTillCompletion(WorkflowInvoker invoker, IRunState runState) { bool hasCompleted = invoker.RunTillCompletion(runState); return(hasCompleted); }
private string GetSafeWfDescription(IRunState runState) { return(runState != null?runState.GetSafeWorkflowDescription() : ""); }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { Action(ActivityInstance.Id); }
private WorkflowRun ProcessWorkflowInContext(WorkflowRun run, IWorkflowEvent wfEvent) { var workflow = run.WorkflowBeingRun; using (Profiler.Measure("WorkflowRunner.Instance.StartWorkflowInContext " + workflow.Id)) { var stopWatch = StartWorkflowTimer(); IRunState runState = null; try { if (!run.IsTemporaryId) { PrecacheWorkflow(run.Id); } using (new SecurityBypassContext()) { var metadata = MetadataFactory.Create(workflow); runState = CreateRunState(metadata, run); if (runState.EffectiveSecurityContext == null) { throw new WorkflowMissingOwnerException(); } } // Wrap a Security bypass with the effective context. This less us "Pop" to run as the effective context. using (CustomContext.SetContext(runState.EffectiveSecurityContext)) { using (new SecurityBypassContext()) { if (runState.Metadata.HasViolations) { MarkRunFailedHasErrors(runState); } else if (run.TriggerDepth > WorkflowTriggerHelper.MaxTriggerDepth) { MarkRunFailedTriggerDepth(runState); } else { var isCompleted = ProcessWorkflow(workflow, runState, wfEvent); } } } } catch (WorkflowRunException ex) { MarkRunFailed(runState, ex); if (runState != null) { runState.FlushInternalArgs(); } } catch (Exception ex) { MarkRunInternalError(runState, ex); if (runState != null) { runState.FlushInternalArgs(); } } finally { if (!Factory.WorkflowRunTaskManager.HasCancelled(runState.RunTaskId)) { run = FinalizeRun(runState); } } EndWorkflowTimer(stopWatch); } return(run); }
/// <summary> /// Run an activity on the invoker /// </summary> /// <param name="runState">The runState for the workflow</param> /// <param name="windowsActivity">The activity to run</param> /// <param name="inputs">The inputs</param> /// <returns></returns> public bool Run(IRunState runState, ActivityImplementationBase windowsActivity, ActivityInputs inputs) { ScheduleActivity(runState, windowsActivity, inputs, null, null); return(RunTillCompletion(runState)); }
/// <summary> /// Resume a paused activity on the invoker /// </summary> /// <param name="runState">The runstate</param> /// <param name="windowsActivity">The activity</param> /// <param name="resumeEvent">The trigger event for the resume</param> /// <returns></returns> public bool Resume(IRunState runState, ActivityImplementationBase windowsActivity, IWorkflowEvent resumeEvent) { ScheduleResume(runState, windowsActivity, resumeEvent, null, null); return(RunTillCompletion(runState)); }
/// <summary> /// Runs when the activity is run by the workflow. /// </summary> /// <param name="context">The run state.</param> /// <param name="inputs">The inputs.</param> public void OnRunNow(IRunState context, ActivityInputs inputs) { var startedKey = GetArgumentKey(StartedArgumentAlias); var listKey = GetArgumentKey(ListArgumentAlias); var appIdKey = GetArgumentKey(ApplicationIdArgumentAlias); var appVersionKey = GetArgumentKey(ApplicationVersionArgumentAlias); var ids = new List <Guid>(); var started = context.GetArgValue <bool?>(ActivityInstance, startedKey) ?? false; if (!started) { // set that the activity has started context.SetArgValue(ActivityInstance, startedKey, true); // retrieve the product var productSku = GetArgumentValue <string>(inputs, ProductSkuArgumentAlias); var product = MarketplaceService.GetProduct(productSku); if (product == null) { throw new WorkflowRunException("Product {0} was not found.", productSku); } // process the included apps and app versions and sort their ids ids.AddRange(GetSortedApplicationIds(product)); } else { // retrieve the current state of the ordered list from the context var list = context.GetArgValue <string>(ActivityInstance, listKey); if (!string.IsNullOrEmpty(list)) { ids.AddRange(list.Split(',').Select(Guid.Parse)); } } // loop over the next id on the list var current = ids.FirstOrDefault(); if (current != default(Guid)) { // set the application id and any specific version info on the output var variables = GetAppVariables(context, current); if (variables.Item1 != Guid.Empty) { context.SetArgValue(ActivityInstance, appIdKey, variables.Item1); context.SetArgValue(ActivityInstance, appVersionKey, variables.Item2); } // remove this id from the list and store it again ids = ids.Skip(1).ToList(); var list = string.Join(",", ids); context.SetArgValue(ActivityInstance, listKey, list); context.ExitPointId = new EntityRef(LoopExitPointAlias); } else { // we have finished context.SetArgValue(ActivityInstance, startedKey, false); context.SetArgValue(ActivityInstance, listKey, null); context.ExitPointId = new EntityRef(FinishedExitPointAlias); } }
/// <summary> /// Initializes a new instance of the <see cref="HtmlReportFormatter"/> class. /// </summary> /// <param name="model">The application model.</param> /// <param name="context">The migration context.</param> /// <param name="state">The run state.</param> /// <param name="writer">The report writer.</param> /// <param name="logger">The logger.</param> public HtmlReportFormatter(IApplicationModel model, MigrationContext context, IRunState state, IReportWriter writer, ILogger logger) : base(model, context, state, writer, logger) { logger.LogTrace(TraceMessages.ReporterConstruct, nameof(HtmlReportFormatter)); }
/// <summary> /// Runs the stage runner. /// </summary> /// <param name="state">The execution state.</param> /// <param name="token">A cancellation token used to cancel this operation.</param> /// <returns>A task used to await the operation.</returns> protected override async Task InvokeRunAsync(IRunState state, CancellationToken token) { _ = state ?? throw new ArgumentNullException(nameof(state)); // Get context var context = Container.GetRequiredService <MigrationContext>(); // Add MSI files from directory if specified if (!string.IsNullOrWhiteSpace(_msiDirectory)) { var dirInfo = new DirectoryInfo(_msiDirectory); var msiFiles = dirInfo.GetFiles("*.msi", SearchOption.AllDirectories); foreach (var file in msiFiles) { _msiFiles.Add(file.FullName); } } // Anything to do? if (_msiFiles.Count == 0) { // Nothing to do, return an error _logger.LogError(ErrorMessages.NoMsiFilesOrDirectorySpecified); context.Errors.Add(new ErrorMessage(ErrorMessages.NoMsiFilesOrDirectorySpecified)); await Task.CompletedTask.ConfigureAwait(false); } // Default unpack directory if not specified if (string.IsNullOrWhiteSpace(_unpackDirectory)) { _unpackDirectory = Environment.CurrentDirectory; } _logger.LogInformation(InformationMessages.UnpackDirectory, _unpackDirectory); // Set up resource containers var model = (AzureIntegrationServicesModel)state.Model; // Create the input criteria (distinct paths to the MSIs) foreach (var path in _msiFiles.Select(p => new FileInfo(p)).GroupBy(f => f.Name).Select(f => f.First())) { var pathFullName = Directory.GetFiles(path.DirectoryName, Path.GetFileName(path.Name)).First(); var name = Path.GetFileNameWithoutExtension(pathFullName); model.MigrationSource.ResourceContainers.Add(new ResourceContainer() { Key = name, Name = name, Type = ModelConstants.ResourceContainerMsi, ContainerLocation = pathFullName }); } // Set working folder context.WorkingFolder = _unpackDirectory; // Call the discover logic (probably should be async) var discoverer = Container.GetRequiredService <BizTalk.Discover.MsiDiscoverer>(); discoverer.Discover(); await Task.CompletedTask.ConfigureAwait(false); }
/// <summary> /// Prints the execution stats. /// </summary> /// <param name="runState">The execution run state.</param> private void PrintExecutionStats(IRunState runState) { if (runState != null && runState.ExecutionState != null) { if (!_options.Options.Verbose) { // Find and print any stage runners that didn't complete if (runState.ExecutionState.Values.Any(s => s.ExecutionState.Any(r => r.State != State.Completed && r.State != State.Skipped))) { foreach (var stageState in runState.ExecutionState.Values) { foreach (var runnerState in stageState.ExecutionState) { if (runnerState.State != State.Completed && runnerState.State != State.Skipped) { var runnerName = runnerState.StageRunner.Name ?? runnerState.StageRunner.GetType().FullName; switch (runnerState.State) { case State.Failed: _logger.LogError(ErrorMessages.StageRunnerFailed, runnerName, runnerState.Error.Message); break; default: _logger.LogWarning(WarningMessages.StageRunnerDidNotCompleteSuccessfully, runnerName, runnerState.State); break; } } } } } } else { // Print detailed execution stats var firstStageState = runState.ExecutionState.Values.Where(s => s.Stage == Stages.Discover).FirstOrDefault(); if (firstStageState != null) { var startTime = firstStageState.Started; foreach (var stageState in runState.ExecutionState.Values) { _logger.LogDebug(TraceMessages.StageExecutionStats, stageState.Stage, stageState.State, (stageState.Started - startTime).TotalMilliseconds, (stageState.Completed - startTime).TotalMilliseconds); foreach (var runnerState in stageState.ExecutionState) { var runnerName = runnerState.StageRunner.Name ?? runnerState.StageRunner.GetType().FullName; switch (runnerState.State) { case State.Failed: _logger.LogDebug(TraceMessages.StageRunnerExecutionStatsWithError, runnerName, stageState.Stage, runnerState.State, (runnerState.Started - startTime).TotalMilliseconds, (runnerState.Completed - startTime).TotalMilliseconds, runnerState.Error.Message); break; default: _logger.LogDebug(TraceMessages.StageRunnerExecutionStats, runnerName, stageState.Stage, runnerState.State, (runnerState.Started - startTime).TotalMilliseconds, (runnerState.Completed - startTime).TotalMilliseconds); break; } } } } } } }
/// <summary> /// Default constructor for dependency injection. /// </summary> /// <param name="model">The application model.</param> /// <param name="context">The migration context.</param> /// <param name="state">The application's run state.</param> /// <param name="writer">An instance of a <see cref="IReportWriter"/> to be used for writing the report.</param> /// <param name="logger">An instance of a <see cref="ILogger"/> to be used for logging within the class.</param> protected BizTalkReporterBase(IApplicationModel model, MigrationContext context, IRunState state, IReportWriter writer, ILogger logger) { Model = (AzureIntegrationServicesModel)model ?? throw new ArgumentNullException(nameof(model)); Context = context ?? throw new ArgumentNullException(nameof(context)); State = state ?? throw new ArgumentNullException(nameof(state)); Writer = writer ?? throw new ArgumentNullException(nameof(writer)); Logger = logger ?? throw new ArgumentNullException(nameof(logger)); }
/// <summary> /// Builds a state path for execution state. /// </summary> /// <param name="statePath">The state path.</param> /// <param name="after">True if event raised after execution, other False for before execution.</param> /// <param name="stage">True to build path for a stage, otherwise False for a stage runner.</param> /// <param name="runState">The execution state.</param> /// <returns>A fully qualified path</returns> private static string BuildStatePath(string statePath, bool after, bool stage, IRunState runState) { var stageState = runState.ExecutionState.Values.Where(s => s.IsCurrent).First(); var stageName = stageState.Stage.ToString("G"); var dateTime = DateTimeOffset.Now.ToString("yyyy-MM-dd.HH-mm-ss.fff", CultureInfo.InvariantCulture); if (stage) { var stageFile = string.Format(CultureInfo.InvariantCulture, "{0}-{1}.json", stageName, dateTime); // Stage if (!after) { // Before execution statePath = Path.Join(statePath, PathResources.BeforeStage, stageFile); } else { // After execution statePath = Path.Join(statePath, PathResources.AfterStage, stageFile); } } else { var stageRunnerState = stageState.ExecutionState.Where(s => s.IsCurrent).First(); var stageRunnerName = stageRunnerState.StageRunner.Name ?? stageRunnerState.StageRunner.GetType().Name; var stageRunnerFile = string.Format(CultureInfo.InvariantCulture, "{0}-{1}.json", stageRunnerName, dateTime); // Stage runner if (!after) { // Before execution statePath = Path.Join(statePath, PathResources.BeforeStageRunner, stageName, stageRunnerFile); } else { // After execution statePath = Path.Join(statePath, PathResources.AfterStageRunner, stageName, stageRunnerFile); } } // Ensure path exists var dirs = new FileInfo(statePath).Directory.FullName; Directory.CreateDirectory(dirs); return(statePath); }
public void ConstructWithSuccess(HtmlReportFormatter reporter, IApplicationModel model, MigrationContext context, IRunState state, IReportWriter writer, ILogger logger, Exception e) { "Given an reporter" .x(() => reporter.Should().BeNull()); "And a model" .x(() => model = TestHelper.BuildModel()); "And run state" .x(() => state = TestHelper.BuildRunState(model)); "And a context" .x(() => context = TestHelper.BuildContext()); "And a writer" .x(() => writer = _mockWriter.Object); "And a logger" .x(() => logger = _mockLogger.Object); "When constructing..." .x(() => e = Record.Exception(() => new HtmlReportFormatter(model, context, state, writer, logger))); "Then the constructor should NOT throw an exception" .x(() => e.Should().BeNull()); }
private WorkflowRun FinalizeRun(IRunState runState) { WorkflowRun run; using (Profiler.Measure("WorkflowRunner.Instance.FinalizeRun")) { using (new SecurityBypassContext()) { try { run = runState.WorkflowRun; runState.CompletedAt = DateTime.UtcNow; if (!run.IsTemporaryId) { run = Entity.Get <WorkflowRun>(runState.WorkflowRun, true, WorkflowRun.WorkflowRunExitPoint_Field, WorkflowRun.HasTimeout_Field, WorkflowRun.PendingActivity_Field, WorkflowRun.RunStepCounter_Field, WorkflowRun.WorkflowRunStatus_Field, WorkflowRun.RunCompletedAt_Field, WorkflowRun.StateInfo_Field); } var deferredRun = run as WorkflowRunDeferred; if (deferredRun != null) { deferredRun.Sync(); } runState.SyncToRun(run); WorkflowRunContext.Current.DeferSave(run); // // Raise a completed child event // if (run != null && run.ParentRun != null && IsRunCompleted(run)) { // This should be hooked into an eventing system. As we don't have one, just run the resume async. runState.WorkflowInvoker.PostEvent(new ChildWorkflowCompletedEvent(run)); } // // Add a restore message to the queue if we are suspended // if (run != null && run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunSuspended) { WorkflowRunContext.Current.DeferAction(() => { // This should be hooked into an eventing system. As we don't have one, just run the resume async. var restoreTask = ResumeWorkflowHandler.CreateBackgroundTask(run, new WorkflowRestoreEvent()); Factory.BackgroundTaskManager.EnqueueTask(restoreTask); }); } // // Let the world know we have finished WorkflowRunContext.Current.DeferAction(() => { if (run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunPaused || run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunCompleted || run.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunFailed) { Factory.WorkflowRunTaskManager.RegisterComplete(run.TaskId, run.Id.ToString(CultureInfo.InvariantCulture)); } else { Factory.WorkflowRunTaskManager.SetResult(run.TaskId, run.Id.ToString(CultureInfo.InvariantCulture)); } HandleDiagnostics(run, run.WorkflowRunStatus_Enum.ToString()); }); } catch (Exception ex) { Workflow workflow = runState != null?Entity.Get <Workflow>(runState.WorkflowRunId) : null; var msg = string.Format("Workflow: {0}. Unexpected error when finalizing the workflow run ({1}), version ({2}).", runState != null ? runState.GetSafeWorkflowDescription() : "", runState != null ? runState.WorkflowRunId : -1L, workflow != null ? workflow.WorkflowVersion : 0); var log = msg + Environment.NewLine + ex.Message; #if DEBUG log += Environment.NewLine + ex.StackTrace; #endif EventLog.Application.WriteError(log); throw new Exception(msg, ex); } } } return(run); }
public void ReportHtmlGenerationHappyPath(HtmlReportFormatter reporter, AzureIntegrationServicesModel model, MigrationContext context, IRunState state, IReportWriter writer, ILogger logger, Exception e) { "Given a model" .x(() => model = TestHelper.BuildModel()); "And run state" .x(() => state = TestHelper.BuildRunState(model)); "And a context" .x(() => context = TestHelper.BuildContext()); "And a writer" .x(() => writer = _mockWriter.Object); "And a logger" .x(() => logger = _mockLogger.Object); "And an reporter" .x(() => reporter = new HtmlReportFormatter(model, context, state, writer, logger)); "When executing the report formatter" .x(() => e = Record.Exception(() => reporter.Report())); "Then there should be no exception" .x(() => e.Should().BeNull()); "The report node should have a source application" .x(() => { _mockWriter.Invocations.Count.Should().Be(5); _mockWriter.Invocations[0].Arguments.Count.Should().Be(2); _mockWriter.Invocations[0].Arguments[0].Should().Be(context.ReportFilePath); _mockWriter.Invocations[0].Arguments[1].Should().NotBeNull(); _mockWriter.Invocations[0].Arguments[1].Should().NotBeEquivalentTo(string.Empty); }); }
/// <summary> /// Get an activity to be used in the error report. /// </summary> private WfActivity GetActivityForError(IRunState runState, WfActivity activity) { var act = runState.WorkflowRun != null ? runState.WorkflowRun.PendingActivity : runState.PendingActivity; return(act ?? activity); }
public void ReportHtmlGenerationNoContainers(HtmlReportFormatter reporter, AzureIntegrationServicesModel model, MigrationContext context, IRunState state, IReportWriter writer, ILogger logger, Exception e) { "Given a model" .x(() => { model = TestHelper.BuildModel(); model.MigrationSource.ResourceContainers.Clear(); //removes any resource containers. }); "And run state" .x(() => state = TestHelper.BuildRunState(model)); "And a context" .x(() => context = TestHelper.BuildContext()); "And a writer" .x(() => writer = _mockWriter.Object); "And a logger" .x(() => logger = _mockLogger.Object); "And an reporter" .x(() => reporter = new HtmlReportFormatter(model, context, state, writer, logger)); "When executing the report formatter" .x(() => e = Record.Exception(() => reporter.Report())); "Then there should be no exception" .x(() => e.Should().BeNull()); "The report node should have a source application" .x(() => { _mockWriter.Invocations.Count.Should().Be(4); _mockWriter.Invocations[0].Arguments.Count.Should().Be(2); _mockWriter.Invocations[0].Arguments[0].Should().Be(context.ReportFilePath); _mockWriter.Invocations[0].Arguments[1].Should().NotBeNull(); var html = (string)_mockWriter.Invocations[0].Arguments[1]; html.Should().Contain("No Input BizTalk Applications"); }); }
/// <summary> /// Build the app container with all services. /// </summary> /// <param name="model">The application model.</param> /// <param name="logger">The provided logger by the tool.</param> /// <param name="state">The run state provided by the tool.</param> /// <returns>A service provider.</returns> public static IServiceProvider BuildContainer(IApplicationModel model, ILogger logger, IRunState state) { _ = model ?? throw new ArgumentNullException(nameof(model)); _ = logger ?? throw new ArgumentNullException(nameof(logger)); _ = state ?? throw new ArgumentNullException(nameof(state)); // Create container var services = new ServiceCollection(); // Add application model services.AddSingleton <IApplicationModel>(model); // Add logger services.AddSingleton <ILogger>(logger); // Add run state services.AddSingleton <IRunState>(state); // Add generators services.AddTransient <IResourceGenerator, YamlResourceGenerator>(); // Add renderers services.AddSingleton <ITemplateRenderer, LiquidTemplateRenderer>(); services.AddSingleton <ISnippetRenderer, LiquidSnippetRenderer>(); // Add repositories services.AddTransient <BizTalk.Discover.Repositories.IFileRepository, BizTalk.Discover.Repositories.FileRepository>(); services.AddTransient <BizTalk.Convert.Repositories.IFileRepository, BizTalk.Convert.Repositories.FileRepository>(); services.AddTransient <IConfigurationRepository, FileConfigurationRepository>(); services.AddTransient <ITemplateRepository, FileTemplateRepository>(); // Add migration context services.AddSingleton <MigrationContext>(); // Add discover components services.AddTransient <BizTalk.Discover.MsiDiscoverer>(); services.AddTransient <BizTalk.Discover.AssemblyDiscoverer>(); // Add parse components services.AddTransient <BizTalk.Parse.ApplicationDefinitionParser>(); services.AddTransient <BizTalk.Parse.BizTalkApplicationParser>(); services.AddTransient <BizTalk.Parse.BindingFileParser>(); services.AddTransient <BizTalk.Parse.BizTalkOrchestrationParser>(); services.AddTransient <BizTalk.Parse.BizTalkPipelineParser>(); services.AddTransient <BizTalk.Parse.DistributionListParser>(); services.AddTransient <BizTalk.Parse.DocumentSchemaParser>(); services.AddTransient <BizTalk.Parse.PipelineComponentParser>(); services.AddTransient <BizTalk.Parse.PropertySchemaPropertyParser>(); services.AddTransient <BizTalk.Parse.OrchestrationCorrelationTypeParser>(); services.AddTransient <BizTalk.Parse.OrchestrationMultiPartMessageTypeParser>(); services.AddTransient <BizTalk.Parse.OrchestrationPortTypeParser>(); services.AddTransient <BizTalk.Parse.OrchestrationServiceLinkTypeParser>(); services.AddTransient <BizTalk.Parse.OrchestrationServiceDeclarationParser>(); services.AddTransient <BizTalk.Parse.ReceivePortParser>(); services.AddTransient <BizTalk.Parse.ReceivePortPipelineDataParser>(); services.AddTransient <BizTalk.Parse.SendPortParser>(); services.AddTransient <BizTalk.Parse.SendPortPipelineDataParser>(); services.AddTransient <BizTalk.Parse.TransformParser>(); // Add analyzer components services.AddTransient <BizTalk.Analyze.ResourceGeneratorAnalyzer>(); services.AddTransient <BizTalk.Analyze.DependencyRules.DP001SchemaDependencyAnalyzer>(); services.AddTransient <BizTalk.Analyze.DependencyRules.DP002TransformDependencyAnalyzer>(); services.AddTransient <BizTalk.Analyze.DependencyRules.DP003OrchestrationDependencyAnalyzer>(); services.AddTransient <BizTalk.Analyze.DependencyRules.DP004ApplicationDependencyAnalyzer>(); services.AddTransient <BizTalk.Analyze.DependencyRules.DP005DistributionListDependencyAnalyzer>(); services.AddTransient <BizTalk.Analyze.DependencyRules.DP006ParentChildDependencyAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.MB001MessageBusAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.AP001ApplicationAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.AP002SystemApplicationAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.AP003ReceivePortScenarioAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.AP004SendPortScenarioAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.AP005OrchestrationScenarioAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.MB002MessageBoxAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.SC001SchemaAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.SC002PropertySchemaAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.RP001FtpReceivePortAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.RP002FileReceivePortAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.RP003HttpReceivePortAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.SP001FtpSendPortAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.SP002FileSendPortAnalyzer>(); services.AddTransient <BizTalk.Analyze.ConversionRules.MA001TransformAnalyzer>(); // Add report components services.AddTransient <BizTalk.Report.IReportWriter, BizTalk.Report.FileReportWriter>(); services.AddTransient <BizTalk.Report.HtmlReportFormatter>(); // Add convert components services.AddSingleton <BizTalk.Convert.IScenarioRouteWalker, BizTalk.Convert.ScenarioRouteWalker>(); services.AddTransient <BizTalk.Convert.TemplateRendererConverter>(); services.AddTransient <BizTalk.Convert.GeneratorRules.AP001ReceiveRoutingSlipGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.AP002SendRoutingSlipGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.AP003ReceiveConfigurationEntryGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.AP004SendConfigurationEntryGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.AP005SendRoutingPropertyGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.AP006ReceiveRoutingPropertyGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.AP007ProcessManagerRoutingSlipGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.AP008ProcessManagerConfigurationEntryGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.SC001DocumentSchemaGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.SC002PropertySchemaGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.MA001TransformGenerator>(); services.AddTransient <BizTalk.Convert.GeneratorRules.WF001WorkflowGenerator>(); // Build provider var provider = services.BuildServiceProvider(); return(provider); }
public void ReportHtmlGenerationNoApplication(HtmlReportFormatter reporter, AzureIntegrationServicesModel model, MigrationContext context, IRunState state, IReportWriter writer, ILogger logger, Exception e) { "Given a model" .x(() => { model = TestHelper.BuildModel(); model.MigrationSource.ResourceContainers.ToList().ForEach(rc => { rc.ResourceContainers.Clear(); rc.ResourceDefinitions.Clear(); }); //removes any resource containers. }); "And run state" .x(() => state = TestHelper.BuildRunState(model)); "And a context" .x(() => context = TestHelper.BuildContext()); "And a writer" .x(() => writer = _mockWriter.Object); "And a logger" .x(() => logger = _mockLogger.Object); "And an reporter" .x(() => reporter = new HtmlReportFormatter(model, context, state, writer, logger)); "When executing the report formatter" .x(() => e = Record.Exception(() => reporter.Report())); "Then there should be no exception" .x(() => e.Should().BeNull()); "The report node should have a source application" .x(() => { _mockWriter.Invocations.Count.Should().Be(4); _mockWriter.Invocations[0].Arguments.Count.Should().Be(2); _mockWriter.Invocations[0].Arguments[0].Should().Be(context.ReportFilePath); _mockWriter.Invocations[0].Arguments[1].Should().NotBeNull(); var invocation = _mockLogger.Invocations.Where(i => i.Arguments[0].ToString() == "Warning").FirstOrDefault(); invocation.Should().NotBeNull(); invocation.Arguments[2].ToString().Should().Contain("no reportable BizTalk application"); }); }
/// <summary> /// Renders the summary report. /// </summary> /// <param name="files">The files to generate.</param> /// <param name="state">The run state.</param> public static void RenderSummaryReport(ReportFileStructure files, IRunState state) { _ = files ?? throw new ArgumentNullException(nameof(files)); _ = state ?? throw new ArgumentNullException(nameof(state)); // Get the container from the file. var container = files.Summary.ReportHtml.DocumentNode.SelectSingleNode(HtmlResources.ReportContentJQuery); // Create a section for the run summary var runInfoNode = HtmlNode.CreateNode(HtmlResources.SummaryRunInfoHeading); container.AppendChild(runInfoNode); var runInfoContainer = runInfoNode.SelectSingleNode(HtmlResources.SummaryRunInfoJQuery); // Render the timings. RenderTimings(runInfoContainer, (RunState)state); // Render the arguments. RenderArguments(runInfoContainer, (RunState)state); // Render the stage runners RenderStageRunners(runInfoContainer, (RunState)state); // Add a placeholder for when there are no source applications. if (files.SourceApplications.Count == 0) { var node = HtmlNode.CreateNode(HtmlResources.SourceApplicationNoneFoundSnippet); container.AppendChild(node); } else { // Build a heading and a list of the file in the source and target reports. var headingNode = HtmlNode.CreateNode(HtmlResources.SummarySourceApplicationHeading); container.AppendChild(headingNode); var sourceContainer = headingNode.SelectSingleNode(HtmlResources.SummarySourceApplicationJQuery); foreach (var source in files.SourceApplications) { var linkNode = HtmlNode.CreateNode(HtmlResources.SnippetEmptyDiv); linkNode.InnerHtml = string.Format(CultureInfo.CurrentCulture, HtmlResources.SummaryReportFileLink, source.Filename, source.SectionName, source.ReportData.Description); sourceContainer.AppendChild(linkNode); } } // Add a placeholder for when there are no target applications. if (files.TargetApplications.Count > 0 && files.TargetMessageBus != null) { // Build a heading and a list of the file in the source and target reports. var headingNode = HtmlNode.CreateNode(HtmlResources.SummaryTargetMessageBusHeading); container.AppendChild(headingNode); var sourceContainer = headingNode.SelectSingleNode(HtmlResources.SummaryTargetMessageBusJQuery); var linkNode = HtmlNode.CreateNode(HtmlResources.SnippetEmptyDiv); linkNode.InnerHtml = string.Format(CultureInfo.CurrentCulture, HtmlResources.SummaryReportFileLink, files.TargetMessageBus.Filename, files.TargetMessageBus.SectionName, files.TargetMessageBus.ReportData.Description); sourceContainer.AppendChild(linkNode); } // Add a placeholder for when there are no target applications. if (files.TargetApplications.Count == 0) { var node = HtmlNode.CreateNode(HtmlResources.TargetApplicationNoneFoundSnippet); container.AppendChild(node); } else { // Build a heading and a list of the file in the source and target reports. var headingNode = HtmlNode.CreateNode(HtmlResources.SummaryTargetApplicationHeading); container.AppendChild(headingNode); var sourceContainer = headingNode.SelectSingleNode(HtmlResources.SummaryTargetApplicationJQuery); foreach (var target in files.TargetApplications) { var linkNode = HtmlNode.CreateNode(HtmlResources.SnippetEmptyDiv); linkNode.InnerHtml = string.Format(CultureInfo.CurrentCulture, HtmlResources.SummaryReportFileLink, target.Filename, target.SectionName, target.ReportData.Application.Description); sourceContainer.AppendChild(linkNode); } } }
public void ConstructWithNullModel(HtmlReportFormatter reporter, IApplicationModel model, MigrationContext context, IRunState state, IReportWriter writer, ILogger logger, Exception e) { "Given an reporter" .x(() => reporter.Should().BeNull()); "And a model" .x(() => model.Should().BeNull()); "And run state" .x(() => state = TestHelper.BuildRunState(model)); "And a context" .x(() => context = TestHelper.BuildContext()); "And a writer" .x(() => writer = _mockWriter.Object); "And a logger" .x(() => logger = _mockLogger.Object); "When constructing with a null model" .x(() => e = Record.Exception(() => new HtmlReportFormatter(model, context, state, writer, logger))); "Then the constructor should throw an exception" .x(() => e.Should().NotBeNull().And.Subject.Should().BeOfType <ArgumentNullException>().Which.ParamName.Should().Be("model")); }
/// <summary> /// Handles the response that was received from a request this activity made. /// </summary> /// <param name="context">The workflow run context.</param> /// <param name="request">The original request object.</param> /// <param name="response">The object that was received in response to the request.</param> protected abstract void OnResponse(IRunState context, TRequest request, TResponse response);
/// <summary> /// The ID of the workflow run this activity is part of. /// </summary> public long GetWorkflowRunId(IRunState runState) { return(runState.WorkflowRunId); }