-
Notifications
You must be signed in to change notification settings - Fork 0
/
args.go
136 lines (113 loc) · 3.33 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
package creatavisor
import (
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
)
const (
rootName = "creatavisor"
genesisDir = "genesis"
upgradesDir = "upgrades"
currentLink = "current"
)
// Config is the information passed in to control the daemon
type Config struct {
Home string
Name string
AllowDownloadBinaries bool
RestartAfterUpgrade bool
}
// 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)
}
// 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"),
}
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/creatavisor 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")
}
// 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
}