Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions internal/commandProcessor/commandProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,14 @@ func ProcessHandlerCommand(cmd types.Cmd) error {
func ProcessHandlerCommandWithDetails(ctx *log.Context, cmd types.Cmd, hEnv types.HandlerEnvironment, extensionName string, seqNum int, downloadFolder string) error {
ctx.Log("message", fmt.Sprintf("processing command for extensionName: %v and seqNum: %v", extensionName, seqNum))
instView := types.RunCommandInstanceView{
ExecutionState: types.Running,
ExecutionMessage: "Execution in progress",
ExitCode: 0,
Output: "",
Error: "",
StartTime: time.Now().UTC().Format(time.RFC3339),
EndTime: "",
ExecutionState: types.Running,
ExecutionMessage: "Execution in progress",
ExitCode: 0,
Output: "",
Error: "",
StartTime: time.Now().UTC().Format(time.RFC3339),
EndTime: "",
ErrorClarificationValue: 0,
}

metadata := types.NewRCMetadata(extensionName, seqNum, downloadFolder, constants.DataDir)
Expand Down
133 changes: 133 additions & 0 deletions internal/constants/errorclarification.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package constants

const (
FileDownload_BadRequest = -41
FileDownload_UnknownError = -40
FileDownload_StorageError = -42
FileDownload_UnhandledError = -43

Internal_CouldNotFindCertificate = -20
Internal_CouldNotDecrypt = -22
Internal_ArtifactCountMismatch = -23
Internal_ArtifactDoesNotExist = -24

SystemError = -1 // CRP will interpret anything > 0 as a user error

// User errors
CommandExecution_BadConfig = 1
CommandExecution_FailureExitCode = 2
CommandExecution_TimedOut = 4
CommandExecution_RunAsCreateProcessFailed = 5
CommandExecution_RunAsUserLogonFailed = 6

CustomerInput_StorageCredsAndMIBothSpecified = 26
CustomerInput_ClientIdObjectIdBothSpecified = 27
CustomerInput_ErrorAndOutputBlobsSame = 28

FileDownload_AccessDenied = 52
FileDownload_DoesNotExist = 53
FileDownload_NetworkingError = 54
FileDownload_GenericError = 55
FileDownload_UnableToWriteFile = 57

Msi_NotFound = 70
Msi_DoesNotHaveRightPermissions = 71
Msi_GenericRetrievalError = 72

AppendBlobCreation_DoesNotExist = 90
AppendBlobCreation_PermissionsIssue = 91
AppendBlobCreation_Other = 92
AppendBlobCreation_InvalidUri = 93
AppendBlobCreation_InvalidMsi = 94

ImmediateRC_ExceededConcurrentLimit = 100
ImmediateRC_TaskCanceled = 101
ImmediateRC_TaskTimeout = 102
ImmediateRC_UnknownFailure = 103
ImmediateRC_UnhandledException = 104
)

func TranslateExitCodeToErrorClarification(exitCode int) int {
switch exitCode {
case ExitCode_Okay:
return 0 // Success, no error clarification needed

// User errors (-100s) -> map to positive user error codes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this mapping for user errors. Directly change ExitCode_* to new positive number for user errors as expected by CRP. Linux returns positive error codes. Please also check what other Linux extensions are doing like CustomScript

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. In RunCommand V2 Windows we just return the error clarification as an int for the exit code.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or in the case of the implementation here it would be the opposite.

case ExitCode_ScriptBlobDownloadFailed:
return FileDownload_GenericError
case ExitCode_BlobCreateOrReplaceFailed:
return AppendBlobCreation_Other
case ExitCode_RunAsLookupUserFailed:
return CommandExecution_RunAsUserLogonFailed

// Service errors (-200s) -> map based on specific failure type

@viveklingaiah viveklingaiah Jul 23, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here. no mapping needed. You can directly use the negative code for service errors. Does CRP expect negative service code for service error ?

case ExitCode_CreateDataDirectoryFailed, ExitCode_RemoveDataDirectoryFailed:
return SystemError // File system operation failures
case ExitCode_GetHandlerSettingsFailed:
return CommandExecution_BadConfig
case ExitCode_SaveScriptFailed:
return FileDownload_UnableToWriteFile
case ExitCode_CommandExecutionFailed:
return CommandExecution_FailureExitCode
case ExitCode_OpenStdOutFileFailed, ExitCode_OpenStdErrFileFailed:
return SystemError // I/O failures
case ExitCode_IncorrectRunAsScriptPath, ExitCode_RunAsIncorrectScriptPath:
return CommandExecution_BadConfig
case ExitCode_RunAsOpenSourceScriptFileFailed:
return FileDownload_DoesNotExist
case ExitCode_RunAsCreateRunAsScriptFileFailed, ExitCode_RunAsCopySourceScriptToRunAsScriptFileFailed:
return FileDownload_UnableToWriteFile
case ExitCode_RunAsLookupUserUidFailed:
return CommandExecution_RunAsUserLogonFailed
case ExitCode_RunAsScriptFileChangeOwnerFailed, ExitCode_RunAsScriptFileChangePermissionsFailed:
return SystemError // Permission/ownership failures
case ExitCode_DownloadArtifactFailed:
return FileDownload_GenericError
case ExitCode_UpgradeInstalledServiceFailed, ExitCode_InstallServiceFailed,
ExitCode_UninstallInstalledServiceFailed, ExitCode_DisableInstalledServiceFailed:
return SystemError // Service management failures
case ExitCode_CopyStateForUpdateFailed:
return FileDownload_UnableToWriteFile
case ExitCode_SkippedImmediateGoalState:
return ImmediateRC_TaskCanceled
case ExitCode_ImmediateTaskTimeout:
return ImmediateRC_TaskTimeout
case ExitCode_ImmediateTaskFailed:
return ImmediateRC_UnknownFailure

// Handle standard Linux exit codes
default:
switch {
case exitCode == 0:
return 0 // Success
case exitCode > 0 && exitCode < 128:
// Standard program exit codes (1-127)
if exitCode == 1 {
return CommandExecution_FailureExitCode
} else if exitCode == 126 {
return CommandExecution_RunAsCreateProcessFailed // Command not executable
} else if exitCode == 127 {
return FileDownload_DoesNotExist // Command not found
} else {
return CommandExecution_FailureExitCode
}
case exitCode >= 128 && exitCode <= 255:
// Signal-terminated processes (128 + signal number)
if exitCode == 130 { // SIGINT (Ctrl+C)
return ImmediateRC_TaskCanceled
} else if exitCode == 137 { // SIGKILL
return ImmediateRC_TaskTimeout
} else if exitCode == 143 { // SIGTERM
return ImmediateRC_TaskCanceled
} else {
return ImmediateRC_UnhandledException
}
case exitCode < 0:
// Negative exit codes - internal errors
return SystemError
default:
// Unknown exit codes
return ImmediateRC_UnknownFailure
}
}
}
Loading