// newDocumentInfo initializes new DocumentInfo object func newDocumentInfo(msg ssmmds.Message, parsedMsg messageContracts.SendCommandPayload) messageContracts.DocumentInfo { documentInfo := new(messageContracts.DocumentInfo) documentInfo.CommandID = getCommandID(*msg.MessageId) documentInfo.Destination = *msg.Destination documentInfo.MessageID = *msg.MessageId documentInfo.RunID = times.ToIsoDashUTC(times.DefaultClock.Now()) documentInfo.CreatedDate = *msg.CreatedDate documentInfo.DocumentName = parsedMsg.DocumentName documentInfo.IsCommand = true documentInfo.DocumentStatus = contracts.ResultStatusInProgress documentInfo.DocumentTraceOutput = "" return *documentInfo }
// runCmdsUsingCmdState takes commandState as an input and executes only those plugins which haven't yet executed. This is functionally // very similar to processSendCommandMessage because everything to do with cmd execution is part of that function right now. func (p *Processor) runCmdsUsingCmdState(context context.T, mdsService service.Service, runPlugins PluginRunner, cancelFlag task.CancelFlag, buildReply replyBuilder, sendResponse engine.SendResponse, command messageContracts.CommandState) { log := context.Log() var pluginConfigurations map[string]*contracts.Configuration pendingPlugins := false pluginConfigurations = make(map[string]*contracts.Configuration) //iterate through all plugins to find all plugins that haven't executed yet. for k, v := range command.PluginsInformation { if v.HasExecuted { log.Debugf("skipping execution of Plugin - %v of command - %v since it has already executed.", k, command.DocumentInformation.CommandID) } else { log.Debugf("Plugin - %v of command - %v will be executed", k, command.DocumentInformation.CommandID) pluginConfigurations[k] = &v.Configuration pendingPlugins = true } } //execute plugins that haven't been executed yet //individual plugins after execution will update interim cmd state file accordingly if pendingPlugins { log.Debugf("executing following plugins of command - %v", command.DocumentInformation.CommandID) for k := range pluginConfigurations { log.Debugf("Plugin: %v", k) } //Since only some plugins of a cmd gets executed here - there is no need to get output from engine & construct the sendReply output. //Instead after all plugins of a command get executed, use persisted data to construct sendReply payload runPlugins(context, command.DocumentInformation.MessageID, pluginConfigurations, sendResponse, cancelFlag) } //read from persisted file newCmdState := commandStateHelper.GetCommandInterimState(log, command.DocumentInformation.CommandID, command.DocumentInformation.Destination, appconfig.DefaultLocationOfCurrent) //construct sendReply payload outputs := make(map[string]*contracts.PluginResult) for k, v := range newCmdState.PluginsInformation { outputs[k] = &v.Result } pluginOutputContent, _ := jsonutil.Marshal(outputs) log.Debugf("plugin outputs %v", jsonutil.Indent(pluginOutputContent)) payloadDoc := buildReply("", outputs) //update interim cmd state file with document level information var documentInfo messageContracts.DocumentInfo // set document level information which wasn't set previously documentInfo.AdditionalInfo = payloadDoc.AdditionalInfo documentInfo.DocumentStatus = payloadDoc.DocumentStatus documentInfo.DocumentTraceOutput = payloadDoc.DocumentTraceOutput documentInfo.RuntimeStatus = payloadDoc.RuntimeStatus //persist final documentInfo. commandStateHelper.PersistDocumentInfo(log, documentInfo, command.DocumentInformation.CommandID, command.DocumentInformation.Destination, appconfig.DefaultLocationOfCurrent) // Skip sending response when the document requires a reboot if documentInfo.DocumentStatus == contracts.ResultStatusSuccessAndReboot { log.Debug("skipping sending response of %v since the document requires a reboot", newCmdState.DocumentInformation.MessageID) return } //send document level reply log.Debug("sending reply on message completion ", outputs) sendResponse(command.DocumentInformation.MessageID, "", outputs) //persist : commands execution in completed folder (terminal state folder) log.Debugf("execution of %v is over. Moving interimState file from Current to Completed folder", newCmdState.DocumentInformation.MessageID) commandStateHelper.MoveCommandState(log, newCmdState.DocumentInformation.CommandID, newCmdState.DocumentInformation.Destination, appconfig.DefaultLocationOfCurrent, appconfig.DefaultLocationOfCompleted) log.Debugf("deleting message") isUpdate := false for pluginName := range pluginConfigurations { if pluginName == appconfig.PluginNameAwsAgentUpdate { isUpdate = true } } if !isUpdate { err := mdsService.DeleteMessage(log, newCmdState.DocumentInformation.MessageID) if err != nil { sdkutil.HandleAwsError(log, err, p.processorStopPolicy) } } else { log.Debug("messageDeletion skipped as it will be handled by external process") } }