99 "io"
1010 "os"
1111 "os/exec"
12+ "path/filepath"
1213
1314 "runtime"
1415 "strings"
@@ -27,7 +28,8 @@ const (
2728 TaskTypePackageRemove = "packageRemove"
2829 TaskTypePackagePurge = "packagePurge"
2930
30- linuxPrivilegedUpdateHelperPath = "/usr/local/libexec/noderax-agent-self-update"
31+ linuxPrivilegedUpdateHelperPath = "/usr/local/libexec/noderax-agent-self-update"
32+ linuxPrivilegedUpdateRequestPath = "/var/lib/noderax-agent/update-request.json"
3133)
3234
3335var (
@@ -125,12 +127,13 @@ func (r *execCommandRunner) Wait() error {
125127}
126128
127129type ShellExecutor struct {
128- defaultTimeout time.Duration
129- goos string
130- lookPath func (string ) (string , error )
131- executablePath func () (string , error )
132- fileExists func (string ) bool
133- newCommand func (context.Context , string , ... string ) commandRunner
130+ defaultTimeout time.Duration
131+ goos string
132+ lookPath func (string ) (string , error )
133+ executablePath func () (string , error )
134+ fileExists func (string ) bool
135+ privilegedUpdateRequestPath string
136+ newCommand func (context.Context , string , ... string ) commandRunner
134137}
135138
136139func NewShellExecutor (defaultTimeout time.Duration ) * ShellExecutor {
@@ -143,7 +146,8 @@ func NewShellExecutor(defaultTimeout time.Duration) *ShellExecutor {
143146 _ , err := os .Stat (path )
144147 return err == nil
145148 },
146- newCommand : newExecCommandRunner ,
149+ privilegedUpdateRequestPath : linuxPrivilegedUpdateRequestPath ,
150+ newCommand : newExecCommandRunner ,
147151 }
148152}
149153
@@ -335,19 +339,17 @@ func (e *ShellExecutor) agentUpdateCommand(payload json.RawMessage) (commandSpec
335339 }
336340
337341 if e .goos == "linux" && e .fileExists (linuxPrivilegedUpdateHelperPath ) {
338- helperArgs := []string {
339- "--target-version" ,
340- targetVersion ,
341- "--target-id" ,
342- targetID ,
343- }
344- if parsed .Rollback {
345- helperArgs = append (helperArgs , "--rollback" )
342+ if err := writeManagedUpdateRequest (e .privilegedUpdateRequestPath , parsed ); err != nil {
343+ return commandSpec {}, fmt .Errorf (
344+ "%w: write privileged update request: %v" ,
345+ ErrUnsupportedExecutionEnvironment ,
346+ err ,
347+ )
346348 }
347349
348350 commandName , commandArgs , err := e .wrapWithSudo (
349351 linuxPrivilegedUpdateHelperPath ,
350- helperArgs ,
352+ nil ,
351353 )
352354 if err != nil {
353355 return commandSpec {}, err
@@ -689,6 +691,47 @@ func formatCommandForLog(name string, args []string) string {
689691 return strings .Join (parts , " " )
690692}
691693
694+ func writeManagedUpdateRequest (path string , payload agentUpdatePayload ) error {
695+ cleanPath := filepath .Clean (strings .TrimSpace (path ))
696+ if cleanPath == "" {
697+ return fmt .Errorf ("request path is empty" )
698+ }
699+
700+ if err := os .MkdirAll (filepath .Dir (cleanPath ), 0o755 ); err != nil {
701+ return fmt .Errorf ("create update request directory: %w" , err )
702+ }
703+
704+ file , err := os .CreateTemp (filepath .Dir (cleanPath ), ".noderax-agent-update-request-*.json" )
705+ if err != nil {
706+ return fmt .Errorf ("create update request file: %w" , err )
707+ }
708+
709+ tempPath := file .Name ()
710+ encoder := json .NewEncoder (file )
711+ encoder .SetEscapeHTML (false )
712+ if err := encoder .Encode (payload ); err != nil {
713+ file .Close ()
714+ _ = os .Remove (tempPath )
715+ return fmt .Errorf ("write update request file: %w" , err )
716+ }
717+ if err := file .Chmod (0o600 ); err != nil {
718+ file .Close ()
719+ _ = os .Remove (tempPath )
720+ return fmt .Errorf ("chmod update request file: %w" , err )
721+ }
722+ if err := file .Close (); err != nil {
723+ _ = os .Remove (tempPath )
724+ return fmt .Errorf ("close update request file: %w" , err )
725+ }
726+
727+ if err := os .Rename (tempPath , cleanPath ); err != nil {
728+ _ = os .Remove (tempPath )
729+ return fmt .Errorf ("replace update request file: %w" , err )
730+ }
731+
732+ return nil
733+ }
734+
692735func strconvQuote (value string ) string {
693736 escaped := strings .ReplaceAll (value , "\\ " , "\\ \\ " )
694737 escaped = strings .ReplaceAll (escaped , "\" " , "\\ \" " )
0 commit comments