cosmos-sdk/cosmovisor/scanner.go

139 lines
3.4 KiB
Go
Raw Normal View History

package cosmovisor
import (
feat: file watcher for cosmovisor (#8590) Adding upgrade file watcher for cosmovisor. Currently the comswisor upgrade mechanism relays on parsing log messages. This is not reliable: + depends on the log level output (x/upgrade uses INFO) + can be hacked by accidentally logging user user content + can be broken by using upgrade name which will break the regex pattern. closes: #7703 closes: #8523 closes: #8651 closes: #8793 closes: #8964 **Depends on**: - #9652 --- Before we can merge this PR, please make sure that all the following items have been checked off. If any of the checklist items are not applicable, please leave them but write a little note why. - [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. - [ ] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md). - [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] Updated relevant documentation (`docs/`) or specification (`x/<module>/spec/`) - [ ] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code). - [ ] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md` - [ ] Re-reviewed `Files changed` in the Github PR explorer - [ ] Review `Codecov Report` in the comment section below once CI passes
2021-08-11 08:03:48 -07:00
"encoding/json"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"time"
)
feat: file watcher for cosmovisor (#8590) Adding upgrade file watcher for cosmovisor. Currently the comswisor upgrade mechanism relays on parsing log messages. This is not reliable: + depends on the log level output (x/upgrade uses INFO) + can be hacked by accidentally logging user user content + can be broken by using upgrade name which will break the regex pattern. closes: #7703 closes: #8523 closes: #8651 closes: #8793 closes: #8964 **Depends on**: - #9652 --- Before we can merge this PR, please make sure that all the following items have been checked off. If any of the checklist items are not applicable, please leave them but write a little note why. - [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. - [ ] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md). - [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] Updated relevant documentation (`docs/`) or specification (`x/<module>/spec/`) - [ ] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code). - [ ] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md` - [ ] Re-reviewed `Files changed` in the Github PR explorer - [ ] Review `Codecov Report` in the comment section below once CI passes
2021-08-11 08:03:48 -07:00
// UpgradeInfo is the update details created by `x/upgrade/keeper.DumpUpgradeInfoToDisk`.
type UpgradeInfo struct {
feat: file watcher for cosmovisor (#8590) Adding upgrade file watcher for cosmovisor. Currently the comswisor upgrade mechanism relays on parsing log messages. This is not reliable: + depends on the log level output (x/upgrade uses INFO) + can be hacked by accidentally logging user user content + can be broken by using upgrade name which will break the regex pattern. closes: #7703 closes: #8523 closes: #8651 closes: #8793 closes: #8964 **Depends on**: - #9652 --- Before we can merge this PR, please make sure that all the following items have been checked off. If any of the checklist items are not applicable, please leave them but write a little note why. - [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. - [ ] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md). - [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] Updated relevant documentation (`docs/`) or specification (`x/<module>/spec/`) - [ ] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code). - [ ] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md` - [ ] Re-reviewed `Files changed` in the Github PR explorer - [ ] Review `Codecov Report` in the comment section below once CI passes
2021-08-11 08:03:48 -07:00
Name string `json:"name"`
Info string `json:"info"`
Height uint `json:"height"`
}
feat: file watcher for cosmovisor (#8590) Adding upgrade file watcher for cosmovisor. Currently the comswisor upgrade mechanism relays on parsing log messages. This is not reliable: + depends on the log level output (x/upgrade uses INFO) + can be hacked by accidentally logging user user content + can be broken by using upgrade name which will break the regex pattern. closes: #7703 closes: #8523 closes: #8651 closes: #8793 closes: #8964 **Depends on**: - #9652 --- Before we can merge this PR, please make sure that all the following items have been checked off. If any of the checklist items are not applicable, please leave them but write a little note why. - [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. - [ ] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md). - [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] Updated relevant documentation (`docs/`) or specification (`x/<module>/spec/`) - [ ] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code). - [ ] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md` - [ ] Re-reviewed `Files changed` in the Github PR explorer - [ ] Review `Codecov Report` in the comment section below once CI passes
2021-08-11 08:03:48 -07:00
type fileWatcher struct {
// full path to a watched file
filename string
interval time.Duration
currentInfo UpgradeInfo
lastModTime time.Time
cancel chan bool
ticker *time.Ticker
needsUpdate bool
initialized bool
}
func newUpgradeFileWatcher(filename string, interval time.Duration) (*fileWatcher, error) {
if filename == "" {
return nil, errors.New("filename undefined")
}
filenameAbs, err := filepath.Abs(filename)
if err != nil {
return nil,
fmt.Errorf("wrong path, %s must be a valid file path, [%w]", filename, err)
}
dirname := filepath.Dir(filename)
info, err := os.Stat(dirname)
if err != nil || !info.IsDir() {
return nil, fmt.Errorf("wrong path, %s must be an existing directory, [%w]", dirname, err)
}
return &fileWatcher{filenameAbs, interval, UpgradeInfo{}, time.Time{}, make(chan bool), time.NewTicker(interval), false, false}, nil
}
func (fw *fileWatcher) Stop() {
close(fw.cancel)
}
// pools the filesystem to check for new upgrade currentInfo. currentName is the name
// of currently running upgrade. The check is rejected if it finds an upgrade with the same
// name.
func (fw *fileWatcher) MonitorUpdate(currentUpgrade UpgradeInfo) <-chan struct{} {
fw.ticker.Reset(fw.interval)
done := make(chan struct{})
fw.cancel = make(chan bool)
fw.needsUpdate = false
go func() {
for {
select {
case <-fw.ticker.C:
if fw.CheckUpdate(currentUpgrade) {
done <- struct{}{}
return
}
case <-fw.cancel:
return
}
}
feat: file watcher for cosmovisor (#8590) Adding upgrade file watcher for cosmovisor. Currently the comswisor upgrade mechanism relays on parsing log messages. This is not reliable: + depends on the log level output (x/upgrade uses INFO) + can be hacked by accidentally logging user user content + can be broken by using upgrade name which will break the regex pattern. closes: #7703 closes: #8523 closes: #8651 closes: #8793 closes: #8964 **Depends on**: - #9652 --- Before we can merge this PR, please make sure that all the following items have been checked off. If any of the checklist items are not applicable, please leave them but write a little note why. - [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. - [ ] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md). - [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] Updated relevant documentation (`docs/`) or specification (`x/<module>/spec/`) - [ ] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code). - [ ] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md` - [ ] Re-reviewed `Files changed` in the Github PR explorer - [ ] Review `Codecov Report` in the comment section below once CI passes
2021-08-11 08:03:48 -07:00
}()
return done
}
// CheckUpdate reads update plan from file and checks if there is a new update request
// currentName is the name of currently running upgrade. The check is rejected if it finds
// an upgrade with the same name.
func (fw *fileWatcher) CheckUpdate(currentUpgrade UpgradeInfo) bool {
if fw.needsUpdate {
return true
}
stat, err := os.Stat(fw.filename)
if err != nil { // file doesn't exists
return false
}
if !stat.ModTime().After(fw.lastModTime) {
return false
}
info, err := parseUpgradeInfoFile(fw.filename)
if err != nil {
log.Fatal("Can't parse upgrade info file. Err: ", err)
return false
}
if !fw.initialized { // daemon has restarted
fw.initialized = true
fw.currentInfo = info
fw.lastModTime = stat.ModTime()
// heuristic: deamon has restarted, so we don't know if we successfully downloaded the upgrade or not.
// so we try to compare the running upgrade name (read from the cosmovisor file) with the upgrade info
if currentUpgrade.Name != fw.currentInfo.Name {
fw.needsUpdate = true
return true
}
}
if info.Height > fw.currentInfo.Height {
fw.currentInfo = info
fw.lastModTime = stat.ModTime()
fw.needsUpdate = true
return true
}
return false
}
func parseUpgradeInfoFile(filename string) (UpgradeInfo, error) {
var ui UpgradeInfo
f, err := os.Open(filename)
if err != nil {
return ui, err
}
defer f.Close()
d := json.NewDecoder(f)
err = d.Decode(&ui)
if err != nil {
return ui, err
}
// required values must be set
if ui.Height == 0 || ui.Name == "" {
return UpgradeInfo{}, fmt.Errorf("invalid upgrade-info.json content. Name and Hight must be not empty. Got: %v", ui)
}
feat: file watcher for cosmovisor (#8590) Adding upgrade file watcher for cosmovisor. Currently the comswisor upgrade mechanism relays on parsing log messages. This is not reliable: + depends on the log level output (x/upgrade uses INFO) + can be hacked by accidentally logging user user content + can be broken by using upgrade name which will break the regex pattern. closes: #7703 closes: #8523 closes: #8651 closes: #8793 closes: #8964 **Depends on**: - #9652 --- Before we can merge this PR, please make sure that all the following items have been checked off. If any of the checklist items are not applicable, please leave them but write a little note why. - [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. - [ ] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md). - [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] Updated relevant documentation (`docs/`) or specification (`x/<module>/spec/`) - [ ] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code). - [ ] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md` - [ ] Re-reviewed `Files changed` in the Github PR explorer - [ ] Review `Codecov Report` in the comment section below once CI passes
2021-08-11 08:03:48 -07:00
return ui, err
}