public HandlerResult ExecuteHandlerProcess_SingleAction(ActionItem a, Dictionary <string, string> dynamicData, bool dryRun = false) { HandlerResult returnResult = HandlerResult.Emtpy; string parms = ResolveConfigAndParameters(a, dynamicData); IHandlerRuntime rt = CreateHandlerRuntime(a.Name, a.Handler); rt.Progress += rt_Progress; if (!WantsStopOrPause()) { a.RunAs?.Impersonate(); HandlerResult r = rt.Execute(parms, dryRun); a.RunAs?.Undo(); if (r.Status > returnResult.Status) { returnResult = r; } } return(returnResult); }
void WriteUnhandledActionException(ActionItem a, Exception ex, bool writeProgress = true, bool writeLog = true) { //todo: serialize exception to composite string string context = "Synapse.Core PlanRuntime"; string message = $"An unhandled exeption occurred in {a.Name}, Plan/Action Instance: {InstanceId}/{a.InstanceId}. Message: {ex.Message}."; if (writeProgress) { HandlerProgressCancelEventArgs e = new HandlerProgressCancelEventArgs(context: context, message: message, status: StatusType.Failed, id: a.InstanceId, sequence: Int32.MaxValue - 100, cancel: false, ex: ex) { ActionName = a.Name }; rt_Progress(this, e); } if (writeLog) { LogMessageEventArgs e = new LogMessageEventArgs(context: context, message: message, level: LogLevel.Fatal, ex: ex); rt_LogMessage(this, e); } }
//note: this doesn't implement SaveExitDataAs( action ); private ExecuteResult SpawnExternal(ActionItem a, Dictionary <string, string> dynamicData, object parentExitData, bool dryRun) { ExecuteResult result = new ExecuteResult(); List <string> args = new List <string>(); Plan container = new Plan(); a.InstanceId = ActionInstanceIdCounter++; container.Name = $"{Name}:{a.Name}"; container.Actions.Add(a.Clone()); container.StartInfo = StartInfo; string planYaml = CryptoHelpers.Encode(container.ToYaml()); args.Add($"/plan:{planYaml}"); args.Add($"/dryRun:{dryRun}"); args.Add($"/taskModel:single"); foreach (string key in dynamicData.Keys) { args.Add($"/{key}:{dynamicData[key]}"); } args.Add($"/data:{parentExitData}"); string arguments = string.Join(" ", args); Process p = new Process(); p.StartInfo.Arguments = arguments; p.StartInfo.FileName = "synapse.cli.exe"; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; p.EnableRaisingEvents = true; //if( a.HasRunAs ) //{ // p.StartInfo.Domain = a.RunAs.Domain; // p.StartInfo.UserName = a.RunAs.UserName; // SecureString pw = new SecureString(); // foreach( char c in a.RunAs.Password ) // pw.AppendChar( c ); // p.StartInfo.Password = pw; //} p.OutputDataReceived += p_OutputDataReceived; p.Start(); result.PId = p.Id; #if sqlite a.UpdateInstanceStatus(StatusType.None, "SpawnExternal", 0, p.Id); #endif #region read this // best practice information on accessing stdout/stderr from mdsn article: // https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput%28v=vs.110%29.aspx // Do not wait for the child process to exit before reading to the end of its redirected stream. // Do not perform a synchronous read to the end of both redirected streams. // string output = p.StandardOutput.ReadToEnd(); // string error = p.StandardError.ReadToEnd(); // p.WaitForExit(); // Use asynchronous read operations on at least one of the streams. #endregion p.BeginOutputReadLine(); p.BeginErrorReadLine(); p.WaitForExit(); result.BranchStatus = result.Status = (StatusType)p.ExitCode; return(result); }
ExecuteResult ExecuteHandlerProcessExternal(SecurityContext parentSecurityContext, ActionItem a, Dictionary <string, string> dynamicData, object parentExitData, bool dryRun = false) { if (!WantsStopOrPause()) { try { //if( !a.HasRunAs ) a.RunAs = parentSecurityContext; a.IngestParentSecurityContext(parentSecurityContext); a.Result = SpawnExternal(a, dynamicData, parentExitData, dryRun); return(a.Result); } catch (Exception ex) { WriteUnhandledActionException(a, ex); return(new ExecuteResult() { Status = StatusType.Failed }); } } else { return(new ExecuteResult()); } }
ExecuteResult ExecuteHandlerProcessInProc(SecurityContext parentSecurityContext, ActionItem a, Dictionary <string, string> dynamicData, object parentExitData, bool dryRun = false) { try { //string parms = ResolveConfigAndParameters( a, dynamicData ); string parms = a.Parameters.GetSerializedValues(Crypto); IHandlerRuntime rt = CreateHandlerRuntime(a); rt.Progress += rt_Progress; rt.LogMessage += rt_LogMessage; if (!WantsStopOrPause()) { a.IngestParentSecurityContext(parentSecurityContext); SecurityContext sc = a.RunAs; //just an alias sc?.Crypto?.InheritSettingsIfRequired(Crypto); HandlerStartInfo startInfo = new HandlerStartInfo(StartInfo) { Parameters = parms, IsDryRun = dryRun, PlanInstanceId = InstanceId, InstanceId = a.InstanceId, ParentExitData = parentExitData, RunAs = sc, Crypto = a.Parameters?.Crypto }; a.Handler.StartInfo = new HandlerStartInfoData(startInfo); sc?.Impersonate(Crypto); a.Result = rt.Execute(startInfo); a.Result.BranchStatus = a.Result.Status; a.Result.SecurityContext = System.Security.Principal.WindowsIdentity.GetCurrent().Name; SaveExitDataAs(a); sc?.Undo(); } return(a.Result); } catch (Exception ex) { WriteUnhandledActionException(a, ex); return(new ExecuteResult() { Status = StatusType.Failed, ExitData = ex.Message }); } }
void ProcessRecursive(IActionContainer parentContext, SecurityContext parentSecurityContext, ActionItem actionGroup, List <ActionItem> actions, ExecuteResult parentResult, Dictionary <string, string> dynamicData, bool dryRun, Func <SecurityContext, ActionItem, Dictionary <string, string>, object, bool, ExecuteResult> executeHandlerMethod) { if (WantsStopOrPause()) { return; } parentContext.EnsureInitialized(); //queryStatus provides the inbound value to ExecuteCase evaluation; it's the ExecuteCase comparison value. //queryStatus is carried downward through successive subtree executions. StatusType queryStatus = parentResult.Status; #region actionGroup if (actionGroup != null && (((actionGroup.ExecuteCase & parentResult.Status) == actionGroup.ExecuteCase) || (actionGroup.ExecuteCase == StatusType.Any))) { actionGroup.EnsureInitialized(); #region actionGroup-forEach if ((actionGroup.HasParameters && actionGroup.Parameters.HasForEach) || (actionGroup.Handler.HasConfig && actionGroup.Handler.Config.HasForEach)) { List <ActionItem> resolvedParmsActionGroup = new List <ActionItem>(); ResolveConfigAndParameters(actionGroup, dynamicData, ref resolvedParmsActionGroup, parentResult.ExitData); foreach (ActionItem ai in resolvedParmsActionGroup) { ai.Parameters.ForEach = null; } actionGroup.InstanceId = ActionInstanceIdCounter++; ActionItem agclone = actionGroup.Clone(); agclone.Result = new ExecuteResult(); parentContext.ActionGroup = agclone; Parallel.ForEach(resolvedParmsActionGroup, a => // foreach( ActionItem a in resolvedParmsActionGroup ) { #if sqlite a.CreateInstance(parentContext, InstanceId); #endif a.InstanceId = ActionInstanceIdCounter++; ActionItem clone = a.Clone(); agclone.Actions.Add(clone); ExecuteResult r = executeHandlerMethod(parentSecurityContext, a, dynamicData, parentResult.ExitData, dryRun); parentContext.ActionGroup.Result.SetBranchStatusChecked(r); parentContext.Result.SetBranchStatusChecked(r); clone.Handler.Type = actionGroup.Handler.Type; clone.Handler.StartInfo = actionGroup.Handler.StartInfo; clone.Result = r; if (r.Status > queryStatus) { queryStatus = r.Status; } if (a.HasActions) { ProcessRecursive(clone, a.RunAs, a.ActionGroup, a.Actions, r, dynamicData, dryRun, executeHandlerMethod); parentContext.ActionGroup.Result.SetBranchStatusChecked(clone.Result); parentContext.Result.SetBranchStatusChecked(clone.Result); if (clone.Result.Status > queryStatus) { queryStatus = clone.Result.Status; } } }); } #endregion #region actionGroup-single else { #if sqlite actionGroup.CreateInstance(parentContext, InstanceId); #endif ResolveConfigAndParameters(actionGroup, dynamicData, parentResult.ExitData); actionGroup.InstanceId = ActionInstanceIdCounter++; ActionItem clone = actionGroup.Clone(); parentContext.ActionGroup = clone; ExecuteResult r = executeHandlerMethod(parentSecurityContext, actionGroup, dynamicData, parentResult.ExitData, dryRun); parentContext.Result.SetBranchStatusChecked(r); clone.Handler.Type = actionGroup.Handler.Type; clone.Handler.StartInfo = actionGroup.Handler.StartInfo; clone.Result = r; if (r.Status > queryStatus) { queryStatus = r.Status; } if (actionGroup.HasActions) { ProcessRecursive(clone, actionGroup.RunAs, null, actionGroup.Actions, r, dynamicData, dryRun, executeHandlerMethod); parentContext.Result.SetBranchStatusChecked(clone.Result); if (clone.Result.Status > queryStatus) { queryStatus = clone.Result.Status; } } } #endregion } #endregion #region actions IEnumerable <ActionItem> actionList = actions.Where(a => (((a.ExecuteCase & queryStatus) == a.ExecuteCase) || (a.ExecuteCase == StatusType.Any))); List <ActionItem> resolvedParmsActions = new List <ActionItem>(); Parallel.ForEach(actionList, a => // foreach( ActionItem a in actionList ) ResolveConfigAndParameters(a, dynamicData, ref resolvedParmsActions, parentResult.ExitData) ); Parallel.ForEach(resolvedParmsActions, a => // foreach( ActionItem a in resolvedParmsActions ) { #if sqlite a.CreateInstance(parentContext, InstanceId); #endif a.InstanceId = ActionInstanceIdCounter++; ActionItem clone = a.Clone(); parentContext.Actions.Add(clone); ExecuteResult r = a.Result; if (r?.Status != StatusType.Failed) { r = executeHandlerMethod(parentSecurityContext, a, dynamicData, parentResult.ExitData, dryRun); } parentContext.Result.SetBranchStatusChecked(r); clone.Handler.Type = a.Handler.Type; clone.Handler.StartInfo = a.Handler.StartInfo; clone.Result = r; if (a.HasActions) { ProcessRecursive(clone, a.RunAs, a.ActionGroup, a.Actions, r, dynamicData, dryRun, executeHandlerMethod); parentContext.Result.SetBranchStatusChecked(clone.Result); } }); #endregion }
public void ResolveConfigAndParameters(Dictionary <string, string> dynamicData, Dictionary <string, ParameterInfo> globalConfigSets, Dictionary <string, ParameterInfo> globalParamSets, ref List <ActionItem> resolvedActions, object parentExitData) { if (Handler == null) { Handler = new HandlerInfo(); } List <object> forEachConfigs = new List <object>(); if (Handler.HasConfig) { ParameterInfo c = Handler.Config; if (globalConfigSets != null && c.HasInheritFrom && globalConfigSets.Keys.Contains(c.InheritFrom)) { c.InheritedValues = globalConfigSets[c.InheritFrom]; } c.Resolve(out forEachConfigs, dynamicData, parentExitData, globalConfigSets); if (globalConfigSets != null && c.HasName) { globalConfigSets[c.Name] = c; } } else { Handler.Config = new ParameterInfo() { }; forEachConfigs.Add(null); } List <object> forEachParms = new List <object>(); if (HasParameters) { ParameterInfo p = Parameters; if (globalParamSets != null && p.HasInheritFrom && globalParamSets.Keys.Contains(p.InheritFrom)) { p.InheritedValues = globalParamSets[p.InheritFrom]; } p.Resolve(out forEachParms, dynamicData, parentExitData, globalParamSets); if (globalParamSets != null && p.HasName) { globalParamSets[p.Name] = p; } } else { Parameters = new ParameterInfo() { }; forEachParms.Add(null); } if (resolvedActions != null) { foreach (object forEachConfig in forEachConfigs) { foreach (object forEachParm in forEachParms) { ActionItem clone = Clone(shallow: false); clone.Handler.Config.Values = forEachConfig; clone.Parameters.Values = forEachParm; resolvedActions.Add(clone); } } } }
HandlerResult ExecuteHandlerProcessExternal(SecurityContext parentSecurityContext, ActionItem a, Dictionary <string, string> dynamicData, bool dryRun = false) { HandlerResult returnResult = HandlerResult.Emtpy; if (!WantsStopOrPause()) { if (!a.HasRunAs) { a.RunAs = parentSecurityContext; } HandlerResult r = SpawnExternal(a, dynamicData, dryRun); if (r.Status > returnResult.Status) { returnResult = r; } } return(returnResult); }
HandlerResult ProcessRecursiveExternal(SecurityContext parentSecurityContext, ActionItem actionGroup, List <ActionItem> actions, HandlerResult result, Dictionary <string, string> dynamicData, bool dryRun = false) { if (WantsStopOrPause()) { return(result); } HandlerResult returnResult = HandlerResult.Emtpy; StatusType queryStatus = result.Status; if (actionGroup != null && actionGroup.ExecuteCase == result.Status) { HandlerResult r = ExecuteHandlerProcessExternal(parentSecurityContext, actionGroup, dynamicData, dryRun); if (r.Status > returnResult.Status) { returnResult = r; } if (actionGroup.HasActions) { r = ProcessRecursiveExternal(parentSecurityContext, null, actionGroup.Actions, r, dynamicData, dryRun); } if (r.Status > returnResult.Status) { returnResult = r; } if (r.Status > queryStatus) { queryStatus = r.Status; } } IEnumerable <ActionItem> actionList = actions.Where(a => a.ExecuteCase == queryStatus); Parallel.ForEach(actionList, a => { HandlerResult r = ExecuteHandlerProcessExternal(parentSecurityContext, a, dynamicData, dryRun); if (a.HasActions) { r = ProcessRecursiveExternal(a.RunAs, a.ActionGroup, a.Actions, r, dynamicData, dryRun); } if (r.Status > returnResult.Status) { returnResult = r; } }); return(returnResult); }