@@ -12,6 +12,7 @@ import (
1212 "net/http"
1313 "os"
1414 "os/exec"
15+ "runtime"
1516 "strings"
1617 "syscall"
1718 "time"
@@ -825,6 +826,34 @@ func (a *Agent) checkForUpdates(ctx context.Context) {
825826 a .logger .Info ().Msg ("Agent updated successfully, restarting..." )
826827}
827828
829+ func determineSelfUpdateArch () string {
830+ switch runtime .GOARCH {
831+ case "amd64" :
832+ return "linux-amd64"
833+ case "arm64" :
834+ return "linux-arm64"
835+ case "arm" :
836+ return "linux-armv7"
837+ }
838+
839+ out , err := exec .Command ("uname" , "-m" ).Output ()
840+ if err != nil {
841+ return ""
842+ }
843+
844+ normalized := strings .ToLower (strings .TrimSpace (string (out )))
845+ switch normalized {
846+ case "x86_64" , "amd64" :
847+ return "linux-amd64"
848+ case "aarch64" , "arm64" :
849+ return "linux-arm64"
850+ case "armv7l" , "armhf" , "armv7" :
851+ return "linux-armv7"
852+ default :
853+ return ""
854+ }
855+ }
856+
828857// selfUpdate downloads the new agent binary and replaces the current one
829858func (a * Agent ) selfUpdate (ctx context.Context ) error {
830859 target := a .primaryTarget ()
@@ -838,28 +867,69 @@ func (a *Agent) selfUpdate(ctx context.Context) error {
838867 return fmt .Errorf ("failed to get executable path: %w" , err )
839868 }
840869
841- // Download new binary
842- url := fmt .Sprintf ("%s/download/pulse-docker-agent" , target .URL )
843- req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , nil )
844- if err != nil {
845- return fmt .Errorf ("failed to create download request: %w" , err )
870+ downloadBase := strings .TrimRight (target .URL , "/" ) + "/download/pulse-docker-agent"
871+ archParam := determineSelfUpdateArch ()
872+
873+ type downloadCandidate struct {
874+ url string
875+ arch string
846876 }
847877
848- if target .Token != "" {
849- req .Header .Set ("X-API-Token" , target .Token )
850- req .Header .Set ("Authorization" , "Bearer " + target .Token )
878+ candidates := make ([]downloadCandidate , 0 , 2 )
879+ if archParam != "" {
880+ candidates = append (candidates , downloadCandidate {
881+ url : fmt .Sprintf ("%s?arch=%s" , downloadBase , archParam ),
882+ arch : archParam ,
883+ })
851884 }
885+ candidates = append (candidates , downloadCandidate {url : downloadBase })
852886
853887 client := a .httpClientFor (target )
854- resp , err := client .Do (req )
855- if err != nil {
856- return fmt .Errorf ("failed to download new binary: %w" , err )
888+ var resp * http.Response
889+ var lastErr error
890+
891+ for _ , candidate := range candidates {
892+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , candidate .url , nil )
893+ if err != nil {
894+ lastErr = fmt .Errorf ("failed to create download request: %w" , err )
895+ continue
896+ }
897+
898+ if target .Token != "" {
899+ req .Header .Set ("X-API-Token" , target .Token )
900+ req .Header .Set ("Authorization" , "Bearer " + target .Token )
901+ }
902+
903+ response , err := client .Do (req )
904+ if err != nil {
905+ lastErr = fmt .Errorf ("failed to download new binary: %w" , err )
906+ continue
907+ }
908+
909+ if response .StatusCode != http .StatusOK {
910+ lastErr = fmt .Errorf ("download failed with status: %s" , response .Status )
911+ response .Body .Close ()
912+ continue
913+ }
914+
915+ resp = response
916+ if candidate .arch != "" {
917+ a .logger .Debug ().
918+ Str ("arch" , candidate .arch ).
919+ Msg ("Self-update: downloaded architecture-specific agent binary" )
920+ } else if archParam != "" {
921+ a .logger .Debug ().Msg ("Self-update: falling back to server default agent binary" )
922+ }
923+ break
857924 }
858- defer resp .Body .Close ()
859925
860- if resp .StatusCode != http .StatusOK {
861- return fmt .Errorf ("download failed with status: %s" , resp .Status )
926+ if resp == nil {
927+ if lastErr == nil {
928+ lastErr = errors .New ("failed to download new binary" )
929+ }
930+ return lastErr
862931 }
932+ defer resp .Body .Close ()
863933
864934 // Create temporary file
865935 tmpFile , err := os .CreateTemp ("" , "pulse-docker-agent-*.tmp" )
0 commit comments