-
Notifications
You must be signed in to change notification settings - Fork 88
/
commands.go
200 lines (169 loc) · 4.84 KB
/
commands.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//go:generate go run _tools/gen_commands.go
package main
import (
"flag"
"fmt"
"os"
"runtime"
"time"
"github.com/Songmu/prompter"
"github.com/Songmu/retry"
"github.com/fatih/color"
"github.com/mackerelio/mackerel-agent/command"
"github.com/mackerelio/mackerel-agent/config"
"github.com/mackerelio/mackerel-agent/pidfile"
"github.com/mackerelio/mackerel-agent/supervisor"
)
/*
+main - mackerel-agent
mackerel-agent [options]
main process of mackerel-agent
*/
func doMain(fs *flag.FlagSet, argv []string) error {
conf, err := resolveConfig(fs, argv)
if err != nil {
return fmt.Errorf("failed to load config: %s", err)
}
return start(conf, make(chan struct{}))
}
/*
+command init - initialize mackerel-agent.conf with apikey
init -apikey=xxxxxxxxxxx [-conf=mackerel-agent.conf]
Initialize mackerel-agent.conf with api key.
- The conf file doesn't exist:
create new file and set the apikey.
- The conf file exists and apikey is unset:
set the apikey.
- The conf file exists and apikey already set:
skip initializing. Don't overwrite apikey and exit normally.
- The conf file exists, but the contents of it is invalid toml:
exit with error.
*/
func doInit(fs *flag.FlagSet, argv []string) error {
err := doInitialize(fs, argv)
if _, ok := err.(apikeyAlreadySetError); ok {
logger.Infof("%s", err)
return nil
}
return err
}
/*
+command supervise - supervisor mode
supervise -conf mackerel-agent.conf ...
run as supervisor mode enabling configuration reloading and crash recovery
*/
func doSupervise(fs *flag.FlagSet, argv []string) error {
if runtime.GOOS == "windows" {
return fmt.Errorf("supervise mode is not supported on windows")
}
copiedArgv := make([]string, len(argv))
copy(copiedArgv, argv)
conf, err := resolveConfig(fs, argv)
if err != nil {
return err
}
setLogLevel(conf.Silent, conf.Verbose)
err = pidfile.Create(conf.Pidfile)
if err != nil {
return err
}
defer func() {
err = pidfile.Remove(conf.Pidfile)
if err != nil {
logger.Warningf("pidfile cant remove. : %s", err.Error())
}
}()
return supervisor.Supervise(os.Args[0], copiedArgv, nil)
}
/*
+command version - display version of mackerel-agent
version
display the version of mackerel-agent
*/
func doVersion(_ *flag.FlagSet, _ []string) error {
fmt.Printf("mackerel-agent version %s (rev %s) [%s %s %s] \n",
version, gitcommit, runtime.GOOS, runtime.GOARCH, runtime.Version())
return nil
}
/*
+command configtest - configtest
configtest
do configtest
*/
func doConfigtest(fs *flag.FlagSet, argv []string) error {
conf, err := resolveConfig(fs, argv)
red := color.New(color.FgRed)
yellow := color.New(color.FgYellow)
if err != nil {
return fmt.Errorf(red.Sprintf("[CRITICAL] failed to test config: %s", err))
}
validResult, err := config.ValidateConfigFile(conf.Conffile)
if err != nil {
return fmt.Errorf(red.Sprintf("[CRITICAL] failed to test config: %s", err))
}
if len(validResult) > 0 {
var messages string
for _, v := range validResult {
if v.SuggestKey == "" {
messages += yellow.Sprintf("[WARNING] %s is unexpected key.\n", v.Key)
} else {
messages += yellow.Sprintf("[WARNING] %s is unexpected key. Did you mean %s ?\n", v.Key, v.SuggestKey)
}
}
return fmt.Errorf(messages)
}
fmt.Fprintf(os.Stderr, "SUCCESS (%s)\n", conf.Conffile)
return nil
}
/*
+command retire - retire the host
retire [-force]
retire the host
*/
func doRetire(fs *flag.FlagSet, argv []string) error {
conf, force, err := resolveConfigForRetire(fs, argv)
if err != nil {
return fmt.Errorf("failed to load config: %s", err)
}
hostID, err := conf.LoadHostID()
if err != nil {
return fmt.Errorf("hostID file is not found or empty")
}
api, err := command.NewMackerelClient(conf.Apibase, conf.Apikey, version, gitcommit, conf.Verbose)
if err != nil {
return fmt.Errorf("faild to create api client: %s", err)
}
if !force && !prompter.YN(fmt.Sprintf("retire this host? (hostID: %s)", hostID), false) {
return fmt.Errorf("retirement is canceled")
}
err = retry.Retry(10, 3*time.Second, func() error {
return api.RetireHost(hostID)
})
if err != nil {
return fmt.Errorf("faild to retire the host: %s", err)
}
logger.Infof("This host (hostID: %s) has been retired.", hostID)
// just to try to remove hostID file.
err = conf.DeleteSavedHostID()
if err != nil {
logger.Warningf("Failed to remove HostID file: %s", err)
}
return nil
}
/*
+command once - output onetime
once
output metrics and meta data of the host one time.
These data are only displayed and not posted to Mackerel.
*/
func doOnce(fs *flag.FlagSet, argv []string) error {
conf, err := resolveConfig(fs, argv)
if err != nil {
logger.Warningf("failed to load config (but `once` must not required conf): %s", err)
conf = &config.Config{}
}
return command.RunOnce(conf, &command.AgentMeta{
Version: version,
Revision: gitcommit,
})
}