mirror of
https://github.com/minio/minio.git
synced 2025-04-20 02:27:50 -04:00
feat: update binary once and push it to other servers (#15407)
This commit is contained in:
parent
916f274c83
commit
8ec888d13d
@ -142,7 +142,16 @@ func (a adminAPIHandlers) ServerUpdateHandler(w http.ResponseWriter, r *http.Req
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, nerr := range globalNotificationSys.DownloadBinary(ctx, u, sha256Sum, releaseInfo) {
|
// Download Binary Once
|
||||||
|
reader, err := downloadBinary(u, mode)
|
||||||
|
if err != nil {
|
||||||
|
logger.LogIf(ctx, fmt.Errorf("server update failed with %w", err))
|
||||||
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push binary to other servers
|
||||||
|
for _, nerr := range globalNotificationSys.VerifyBinary(ctx, u, sha256Sum, releaseInfo, reader) {
|
||||||
if nerr.Err != nil {
|
if nerr.Err != nil {
|
||||||
err := AdminError{
|
err := AdminError{
|
||||||
Code: AdminUpdateApplyFailure,
|
Code: AdminUpdateApplyFailure,
|
||||||
@ -156,7 +165,7 @@ func (a adminAPIHandlers) ServerUpdateHandler(w http.ResponseWriter, r *http.Req
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = downloadBinary(u, sha256Sum, releaseInfo, mode)
|
err = verifyBinary(u, sha256Sum, releaseInfo, mode, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.LogIf(ctx, fmt.Errorf("server update failed with %w", err))
|
logger.LogIf(ctx, fmt.Errorf("server update failed with %w", err))
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
|
@ -356,8 +356,8 @@ func (sys *NotificationSys) DownloadProfilingData(ctx context.Context, writer io
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadBinary - asks remote peers to download a new binary from the URL and to verify the checksum
|
// VerifyBinary - asks remote peers to verify the checksum
|
||||||
func (sys *NotificationSys) DownloadBinary(ctx context.Context, u *url.URL, sha256Sum []byte, releaseInfo string) []NotificationPeerErr {
|
func (sys *NotificationSys) VerifyBinary(ctx context.Context, u *url.URL, sha256Sum []byte, releaseInfo string, reader []byte) []NotificationPeerErr {
|
||||||
ng := WithNPeers(len(sys.peerClients))
|
ng := WithNPeers(len(sys.peerClients))
|
||||||
for idx, client := range sys.peerClients {
|
for idx, client := range sys.peerClients {
|
||||||
if client == nil {
|
if client == nil {
|
||||||
@ -365,7 +365,7 @@ func (sys *NotificationSys) DownloadBinary(ctx context.Context, u *url.URL, sha2
|
|||||||
}
|
}
|
||||||
client := client
|
client := client
|
||||||
ng.Go(ctx, func() error {
|
ng.Go(ctx, func() error {
|
||||||
return client.DownloadBinary(ctx, u, sha256Sum, releaseInfo)
|
return client.VerifyBinary(ctx, u, sha256Sum, releaseInfo, reader)
|
||||||
}, idx, *client.host)
|
}, idx, *client.host)
|
||||||
}
|
}
|
||||||
return ng.Wait()
|
return ng.Wait()
|
||||||
|
@ -422,16 +422,18 @@ type binaryInfo struct {
|
|||||||
URL *url.URL
|
URL *url.URL
|
||||||
Sha256Sum []byte
|
Sha256Sum []byte
|
||||||
ReleaseInfo string
|
ReleaseInfo string
|
||||||
|
BinaryFile []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadBinary - sends download binary message to remote peers.
|
// VerifyBinary - sends verify binary message to remote peers.
|
||||||
func (client *peerRESTClient) DownloadBinary(ctx context.Context, u *url.URL, sha256Sum []byte, releaseInfo string) error {
|
func (client *peerRESTClient) VerifyBinary(ctx context.Context, u *url.URL, sha256Sum []byte, releaseInfo string, readerInput []byte) error {
|
||||||
values := make(url.Values)
|
values := make(url.Values)
|
||||||
var reader bytes.Buffer
|
var reader bytes.Buffer
|
||||||
if err := gob.NewEncoder(&reader).Encode(binaryInfo{
|
if err := gob.NewEncoder(&reader).Encode(binaryInfo{
|
||||||
URL: u,
|
URL: u,
|
||||||
Sha256Sum: sha256Sum,
|
Sha256Sum: sha256Sum,
|
||||||
ReleaseInfo: releaseInfo,
|
ReleaseInfo: releaseInfo,
|
||||||
|
BinaryFile: readerInput,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -770,7 +770,7 @@ func (s *peerRESTServer) DownloadBinaryHandler(w http.ResponseWriter, r *http.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = downloadBinary(info.URL, info.Sha256Sum, info.ReleaseInfo, getMinioMode()); err != nil {
|
if err = verifyBinary(info.URL, info.Sha256Sum, info.ReleaseInfo, getMinioMode(), info.BinaryFile); err != nil {
|
||||||
s.writeErrorResponse(w, err)
|
s.writeErrorResponse(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@ -505,26 +506,38 @@ func getUpdateReaderFromURL(u *url.URL, transport http.RoundTripper, mode string
|
|||||||
|
|
||||||
var updateInProgress uint32
|
var updateInProgress uint32
|
||||||
|
|
||||||
func downloadBinary(u *url.URL, sha256Sum []byte, releaseInfo string, mode string) (err error) {
|
// Function to get the reader from an architecture
|
||||||
|
func downloadBinary(u *url.URL, mode string) (readerReturn []byte, err error) {
|
||||||
|
transport := getUpdateTransport(30 * time.Second)
|
||||||
|
var reader io.ReadCloser
|
||||||
|
if u.Scheme == "https" || u.Scheme == "http" {
|
||||||
|
reader, err = getUpdateReaderFromURL(u, transport, mode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reader, err = getUpdateReaderFromFile(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert a Reader to bytes
|
||||||
|
binaryFile, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return binaryFile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyBinary(u *url.URL, sha256Sum []byte, releaseInfo string, mode string, reader []byte) (err error) {
|
||||||
if !atomic.CompareAndSwapUint32(&updateInProgress, 0, 1) {
|
if !atomic.CompareAndSwapUint32(&updateInProgress, 0, 1) {
|
||||||
return errors.New("update already in progress")
|
return errors.New("update already in progress")
|
||||||
}
|
}
|
||||||
defer atomic.StoreUint32(&updateInProgress, 0)
|
defer atomic.StoreUint32(&updateInProgress, 0)
|
||||||
|
|
||||||
transport := getUpdateTransport(30 * time.Second)
|
transport := getUpdateTransport(30 * time.Second)
|
||||||
var reader io.ReadCloser
|
|
||||||
if u.Scheme == "https" || u.Scheme == "http" {
|
|
||||||
reader, err = getUpdateReaderFromURL(u, transport, mode)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reader, err = getUpdateReaderFromFile(u)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := selfupdate.Options{
|
opts := selfupdate.Options{
|
||||||
Hash: crypto.SHA256,
|
Hash: crypto.SHA256,
|
||||||
Checksum: sha256Sum,
|
Checksum: sha256Sum,
|
||||||
@ -552,7 +565,7 @@ func downloadBinary(u *url.URL, sha256Sum []byte, releaseInfo string, mode strin
|
|||||||
opts.Verifier = v
|
opts.Verifier = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = selfupdate.PrepareAndCheckBinary(reader, opts); err != nil {
|
if err = selfupdate.PrepareAndCheckBinary(bytes.NewReader(reader), opts); err != nil {
|
||||||
var pathErr *os.PathError
|
var pathErr *os.PathError
|
||||||
if errors.As(err, &pathErr) {
|
if errors.As(err, &pathErr) {
|
||||||
return AdminError{
|
return AdminError{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user