This repository has been archived by the owner on May 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
args.go
159 lines (133 loc) · 3.98 KB
/
args.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package cosmovisor
import (
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
)
const (
rootName = "cosmovisor"
genesisDir = "genesis"
upgradesDir = "upgrades"
backupsDir = "backups"
currentLink = "current"
)
// Config is the information passed in to control the daemon
type Config struct {
Home string
Name string
AllowDownloadBinaries bool
RestartAfterUpgrade bool
DataDir string
}
// Root returns the root directory where all info lives
func (cfg *Config) Root() string {
return filepath.Join(cfg.Home, rootName)
}
// GenesisBin is the path to the genesis binary - must be in place to start manager
func (cfg *Config) GenesisBin() string {
return filepath.Join(cfg.Root(), genesisDir, "bin", cfg.Name)
}
// UpgradeBin is the path to the binary for the named upgrade
func (cfg *Config) UpgradeBin(upgradeName string) string {
return filepath.Join(cfg.UpgradeDir(upgradeName), "bin", cfg.Name)
}
// UpgradeDir is the directory named upgrade
func (cfg *Config) UpgradeDir(upgradeName string) string {
safeName := url.PathEscape(upgradeName)
return filepath.Join(cfg.Root(), upgradesDir, safeName)
}
// BackupDir is the directory for backups.
func (cfg *Config) BackupDir(upgradeName string) string {
safeName := url.PathEscape(upgradeName)
return filepath.Join(cfg.Root(), backupsDir, safeName)
}
// SymLinkToGenesis Symlink to genesis
func (cfg *Config) SymLinkToGenesis() (string, error) {
genesis := filepath.Join(cfg.Root(), genesisDir)
link := filepath.Join(cfg.Root(), currentLink)
if err := os.Symlink(genesis, link); err != nil {
return "", err
}
// and return the genesis binary
return cfg.GenesisBin(), nil
}
// CurrentBin is the path to the currently selected binary (genesis if no link is set)
// This will resolve the symlink to the underlying directory to make it easier to debug
func (cfg *Config) CurrentBin() (string, error) {
cur := filepath.Join(cfg.Root(), currentLink)
// if nothing here, fallback to genesis
info, err := os.Lstat(cur)
if err != nil {
// Create symlink to the genesis
return cfg.SymLinkToGenesis()
}
// if it is there, ensure it is a symlink
if info.Mode()&os.ModeSymlink == 0 {
// Create symlink to the genesis
return cfg.SymLinkToGenesis()
}
// resolve it
dest, err := os.Readlink(cur)
if err != nil {
// Create symlink to the genesis
return cfg.SymLinkToGenesis()
}
// and return the binary
return filepath.Join(dest, "bin", cfg.Name), nil
}
// GetConfigFromEnv will read the environmental variables into a config
// and then validate it is reasonable
func GetConfigFromEnv() (*Config, error) {
cfg := &Config{
Home: os.Getenv("DAEMON_HOME"),
Name: os.Getenv("DAEMON_NAME"),
DataDir: os.Getenv("DAEMON_BACKUP_DATA_DIR"),
}
if os.Getenv("DAEMON_ALLOW_DOWNLOAD_BINARIES") == "true" {
cfg.AllowDownloadBinaries = true
}
if os.Getenv("DAEMON_RESTART_AFTER_UPGRADE") == "true" {
cfg.RestartAfterUpgrade = true
}
if err := cfg.validate(); err != nil {
return nil, err
}
return cfg, nil
}
// validate returns an error if this config is invalid.
// it enforces Home/cosmovisor is a valid directory and exists,
// and that Name is set
func (cfg *Config) validate() error {
if cfg.Name == "" {
return errors.New("DAEMON_NAME is not set")
}
if cfg.Home == "" {
return errors.New("DAEMON_HOME is not set")
}
if !filepath.IsAbs(cfg.Home) {
return errors.New("DAEMON_HOME must be an absolute path")
}
if cfg.DataDir != "" {
if !filepath.IsAbs(cfg.DataDir) {
return errors.New("DAEMON_BACKUP_DATA_DIR must be an absolute path")
}
info, err := os.Stat(cfg.DataDir)
if err != nil {
return fmt.Errorf("cannot stat data dir: %w", err)
}
if !info.IsDir() {
return fmt.Errorf("%s is not a directory", info.Name())
}
}
// ensure the root directory exists
info, err := os.Stat(cfg.Root())
if err != nil {
return fmt.Errorf("cannot stat home dir: %w", err)
}
if !info.IsDir() {
return fmt.Errorf("%s is not a directory", info.Name())
}
return nil
}