where this looks for its updates
I might have this wrong, but i assumed that this looks for a new binary from a server, and then does the update (without forking :) )
The example does not show the server being involved.
the other one i am playing with is this right now. https://github.com/sanbornm/go-selfupdate
@joeblew99 this package doesn't actually look for anything, it's completely up to you how to grab the updated binary... I'll get a simple example up for you sometime later today, it's pretty simple using http.
I do intend to update this package to use https://github.com/go-playground/kms for the graceful shutdown portion of the logic.
thanks for the update.
btw https://github.com/sanbornm/go-selfupdate code has a nice way to package code for each golang OS ARCH and upload it to the Update Server. They have put alot of functionality into it.
On Thu, Dec 22, 2016 at 1:41 PM Dean Karn [email protected] wrote:
@joeblew99 https://github.com/joeblew99 this package doesn't actually look for anything, it's completely up to you how to grab the updated binary... I'll get a simple example up for you sometime later today, it's pretty simple using http.
I do intend to update this package to use https://github.com/go-playground/kms for the graceful shutdown portion of the logic.
— You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/go-playground/spoon/issues/1#issuecomment-268791893, or mute the thread https://github.com/notifications/unsubscribe-auth/ALcac47bUH-7HyTj89O0zb0L9kdZfcYZks5rKnALgaJpZM4LT7BX .
Thanks @joeblew99, our packages are a little different though, I not only update the binary but also allow for restarting the application gracefully after the update as well.
This package is not yet v1.0, need to integrate my kms for better graceful shutdown of an entire application not just http; also because of the current signal I believe this will only work on *nix systems and not windows...yet.
so here is a quick example of updating and restarting:
// server
checksum := func(checksumOnly bool, path string, w http.ResponseWriter, r *http.Request) {
existingChecksum := r.Header.Get(updateCurrentChecksumKey)
if existingChecksum == "" {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
_, err := os.Stat(path)
if err != nil {
// no file exists on disk
return
}
f, err := os.Open(path)
if err != nil {
http.Error(w, "Error Opening File", http.StatusInternalServerError)
return
}
defer f.Close()
hash := sha256.New()
_, err = io.Copy(hash, f)
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
currentChecksum := fmt.Sprintf("%x", string(hash.Sum(nil)))
// current version is equal, nothing to update.
if existingChecksum == currentChecksum {
return
}
w.Header().Set("checksum", currentChecksum)
if checksumOnly {
return
}
// reset file
f.Seek(0, 0)
_, err = io.Copy(w, f)
if err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
}
fn := func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" && r.Method != "HEAD" {
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
apiKey := r.Header.Get(updateAPIKey)
if apiKey != fnAPIKey {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}
checksum(r.Method == "HEAD", updatePath, w, r)
}
// use fn as http handler
// client
req, err := http.NewRequest("GET", updateURL, nil)
if err != nil {
panic(err)
}
req.Header.Set("Update-Api-Key", updateAPIKey)
upgradeFn = func() {
m.Lock()
defer m.Unlock()
cc := sp.Checksum()
// request upgrade...
client := &http.Client{}
req.Method = "HEAD"
req.Header.Set("Current-Checksum", cc)
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
checksum := resp.Header.Get("checksum")
if checksum == "" {
return
}
// there are updates....processing
req.Method = "GET"
resp, err = client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
if err = sp.UpgradeFullBinary(resp.Body, checksum); err != nil {
return
}
}
// run upgradeFn in a CRON job