Skip to content

Commit 22ead1c

Browse files
committed
daemon: add daemon module
`tt daemon` module is used to manage HTTP server running on the background. HTTP server can process `tt` commands such as `start`, `status`, etc. Daemon can be configurated with `tt_daemon.yaml` config. The following set of commands is implemented: * `tt daemon start` - launch of a daemon; * `tt daemon stop` - terminate of the daemon; * `tt daemon status` - get daemon status; * `tt daemon restart` - daemon restart. Closes #10
1 parent 7bfe774 commit 22ead1c

26 files changed

+1554
-30
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1010
### Added
1111

1212
- Module ``tt init``, to create tt environment configuration file.
13+
- Module ``tt daemon`` to launch ``tt`` as a daemon HTTP server.
1314

1415
## [0.1.0] - 2022-10-12
1516

README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,4 @@ Common description. For a detailed description, use ``tt help command`` .
314314
* ``install`` - install tarantool/tt.
315315
* ``remove`` - remove tarantool/tt.
316316
* ``init`` - create tt environment configuration file.
317+
* ``daemon`` - manage ``tt`` daemon HTTP server.

cli/cmd/clean.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func internalCleanModule(cmdCtx *cmdcontext.CmdCtx, args []string) error {
110110
}
111111

112112
for _, run := range cmdCtx.Running {
113-
status := running.Status(cmdCtx, &run)
113+
status := running.Status(cmdCtx, run.PIDFile)
114114
if status == running.InstStateStopped {
115115
var statusMsg string
116116

cli/cmd/daemon.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package cmd
2+
3+
import (
4+
"github.com/apex/log"
5+
"github.com/spf13/cobra"
6+
"github.com/tarantool/tt/cli/cmdcontext"
7+
"github.com/tarantool/tt/cli/configure"
8+
"github.com/tarantool/tt/cli/daemon"
9+
"github.com/tarantool/tt/cli/modules"
10+
"github.com/tarantool/tt/cli/running"
11+
)
12+
13+
// NewDaemonCmd creates daemon command.
14+
func NewDaemonCmd() *cobra.Command {
15+
var daemonCmd = &cobra.Command{
16+
Use: "daemon",
17+
Short: "Perform manipulations with the tarantool daemon",
18+
}
19+
20+
var startCmd = &cobra.Command{
21+
Use: "start",
22+
Short: "start tt daemon",
23+
Run: func(cmd *cobra.Command, args []string) {
24+
if len(args) != 0 {
25+
log.Fatalf("Wrong number of arguments")
26+
}
27+
28+
err := modules.RunCmd(&cmdCtx, cmd.Name(), &modulesInfo,
29+
internalDaemonStartModule, args)
30+
if err != nil {
31+
log.Fatalf(err.Error())
32+
}
33+
},
34+
}
35+
36+
var stopCmd = &cobra.Command{
37+
Use: "stop",
38+
Short: "stop tt daemon",
39+
Run: func(cmd *cobra.Command, args []string) {
40+
if len(args) != 0 {
41+
log.Fatalf("Wrong number of arguments")
42+
}
43+
44+
err := modules.RunCmd(&cmdCtx, cmd.Name(), &modulesInfo,
45+
internalDaemonStopModule, args)
46+
if err != nil {
47+
log.Fatalf(err.Error())
48+
}
49+
},
50+
}
51+
52+
var statusCmd = &cobra.Command{
53+
Use: "status",
54+
Short: "status of tt daemon",
55+
Run: func(cmd *cobra.Command, args []string) {
56+
if len(args) != 0 {
57+
log.Fatalf("Wrong number of arguments")
58+
}
59+
60+
err := modules.RunCmd(&cmdCtx, cmd.Name(), &modulesInfo,
61+
internalDaemonStatusModule, args)
62+
if err != nil {
63+
log.Fatalf(err.Error())
64+
}
65+
},
66+
}
67+
68+
var restartCmd = &cobra.Command{
69+
Use: "restart",
70+
Short: "restart tt daemon",
71+
Run: func(cmd *cobra.Command, args []string) {
72+
if len(args) != 0 {
73+
log.Fatalf("Wrong number of arguments")
74+
}
75+
76+
err := modules.RunCmd(&cmdCtx, cmd.Name(), &modulesInfo,
77+
internalDaemonRestartModule, args)
78+
if err != nil {
79+
log.Fatalf(err.Error())
80+
}
81+
},
82+
}
83+
84+
daemonSubCommands := []*cobra.Command{
85+
startCmd,
86+
stopCmd,
87+
statusCmd,
88+
restartCmd,
89+
}
90+
91+
for _, cmd := range daemonSubCommands {
92+
daemonCmd.AddCommand(cmd)
93+
}
94+
95+
return daemonCmd
96+
}
97+
98+
// internalDaemonStartModule is a default restart module.
99+
func internalDaemonRestartModule(cmdCtx *cmdcontext.CmdCtx, args []string) error {
100+
if err := internalDaemonStopModule(cmdCtx, args); err != nil {
101+
return err
102+
}
103+
104+
if err := internalDaemonStartModule(cmdCtx, args); err != nil {
105+
return err
106+
}
107+
108+
return nil
109+
}
110+
111+
// internalDaemonStartModule is a default start module.
112+
func internalDaemonStartModule(cmdCtx *cmdcontext.CmdCtx, args []string) error {
113+
opts, err := configure.GetDaemonOpts(cmdCtx.Cli.DaemonCfgPath)
114+
if err != nil {
115+
return err
116+
}
117+
118+
if err = running.FillDaemonCtx(opts, cmdCtx); err != nil {
119+
log.Fatalf(err.Error())
120+
}
121+
122+
if err := daemon.RunHTTPServerOnBackground(cmdCtx); err != nil {
123+
log.Fatalf(err.Error())
124+
}
125+
126+
return nil
127+
}
128+
129+
// internalDaemonStopModule is a default stop module.
130+
func internalDaemonStopModule(cmdCtx *cmdcontext.CmdCtx, args []string) error {
131+
opts, err := configure.GetDaemonOpts(cmdCtx.Cli.DaemonCfgPath)
132+
if err != nil {
133+
return err
134+
}
135+
136+
if err = running.FillDaemonCtx(opts, cmdCtx); err != nil {
137+
log.Fatalf(err.Error())
138+
}
139+
140+
if err := running.Stop(cmdCtx, cmdCtx.Daemon.PIDFile,
141+
cmdCtx.Daemon.ConsoleSocket, "Daemon"); err != nil {
142+
return err
143+
}
144+
145+
return nil
146+
}
147+
148+
// internalDaemonStatusModule is a default status module.
149+
func internalDaemonStatusModule(cmdCtx *cmdcontext.CmdCtx, args []string) error {
150+
opts, err := configure.GetDaemonOpts(cmdCtx.Cli.DaemonCfgPath)
151+
if err != nil {
152+
return err
153+
}
154+
155+
if err = running.FillDaemonCtx(opts, cmdCtx); err != nil {
156+
log.Fatalf(err.Error())
157+
}
158+
159+
log.Info(running.Status(cmdCtx, cmdCtx.Daemon.PIDFile))
160+
161+
return nil
162+
}

cli/cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ func NewCmdRoot() *cobra.Command {
117117
NewRemoveCmd(),
118118
NewPackCmd(),
119119
NewInitCmd(),
120+
NewDaemonCmd(),
120121
)
121122
if err := injectCmds(rootCmd); err != nil {
122123
panic(err.Error())

cli/cmd/status.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func internalStatusModule(cmdCtx *cmdcontext.CmdCtx, args []string) error {
3838
}
3939

4040
for _, run := range cmdCtx.Running {
41-
log.Infof("%s: %s", run.InstName, running.Status(cmdCtx, &run))
41+
log.Infof("%s: %s", run.InstName, running.Status(cmdCtx, run.PIDFile))
4242
}
4343

4444
return nil

cli/cmd/stop.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func internalStopModule(cmdCtx *cmdcontext.CmdCtx, args []string) error {
3838
}
3939

4040
for _, run := range cmdCtx.Running {
41-
if err = running.Stop(cmdCtx, &run); err != nil {
41+
if err = running.Stop(cmdCtx, run.PIDFile, run.ConsoleSocket, "Instance"); err != nil {
4242
log.Infof(err.Error())
4343
}
4444
}

cli/cmdcontext/cmdcontext.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type CmdCtx struct {
1414
Running []RunningCtx
1515
// Connect contains information for connecting to the instance.
1616
Connect ConnectCtx
17+
Daemon DaemonCtx
1718
// CommandName contains name of the command.
1819
CommandName string
1920
// Create contains information to create an application.
@@ -37,6 +38,8 @@ type CliCtx struct {
3738
LocalLaunchDir string
3839
// Path to Tarantool CLI (tarantool.yaml) config.
3940
ConfigPath string
41+
// Path to tt daemon (tt_daemon.yaml) config.
42+
DaemonCfgPath string
4043
// Path to Tarantool executable (detected if CLI launch is local).
4144
TarantoolExecutable string
4245
// Tarantool version.
@@ -204,3 +207,31 @@ type InitCtx struct {
204207
// so init does not try to get directories information from exitsting config files.
205208
SkipConfig bool
206209
}
210+
211+
// DaemonCtx contains information for running an daemon instance.
212+
type DaemonCtx struct {
213+
// Port is a port number to be used for daemon http server.
214+
Port int
215+
// PIDFile is a path of a file contains pid of daemon process.
216+
PIDFile string
217+
// LogPath is a path to a file contains log of daemon process.
218+
LogPath string
219+
// LogMaxSize is the maximum size in megabytes of the log file
220+
// before it gets rotated. It defaults to 100 megabytes.
221+
LogMaxSize int
222+
// LogMaxBackups is the maximum number of old log files to retain.
223+
// The default is to retain all old log files (though LogMaxAge may
224+
// still cause them to get deleted).
225+
LogMaxBackups int
226+
// LogMaxAge is the maximum number of days to retain old log files
227+
// based on the timestamp encoded in their filename. Note that a
228+
// day is defined as 24 hours and may not exactly correspond to
229+
// calendar days due to daylight savings, leap seconds, etc. The
230+
// default is not to remove old log files based on age.
231+
LogMaxAge int
232+
// ListenInterface is a network interface the IP address
233+
// should be found on to bind http server socket.
234+
ListenInterface string
235+
// Control UNIX socket for started instance.
236+
ConsoleSocket string
237+
}

cli/config/daemon_cfg.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package config
2+
3+
// DaemonCfg used to store all information from the
4+
// tt_daemon.yaml configuration file.
5+
type DaemonCfg struct {
6+
DaemonConfig *DaemonOpts `mapstructure:"daemon" yaml:"daemon"`
7+
}
8+
9+
// DaemonOpts stores information about tt daemon configuration.
10+
// Filled in when parsing the tt_daemon.yaml configuration file.
11+
//
12+
// tt_daemon.yaml file format:
13+
// daemon:
14+
// run_dir: path
15+
// log_dir: path
16+
// log_maxsize: num (MB)
17+
// log_maxage: num (Days)
18+
// log_maxbackups: num
19+
// log_file: string (file name)
20+
// listen_interface: string
21+
// port: num
22+
// pidfile: string (file name)
23+
type DaemonOpts struct {
24+
// PIDFile is name of file contains pid of daemon process.
25+
PIDFile string `mapstructure:"pidfile"`
26+
// Port is a port number to be used for daemon http server.
27+
Port int `mapstructure:"port"`
28+
// LogDir is a directory that stores log files.
29+
LogDir string `mapstructure:"log_dir"`
30+
// LogFile is a name of file contains log of daemon process.
31+
LogFile string `mapstructure:"log_file"`
32+
// LogMaxSize is a maximum size in MB of the log file before
33+
// it gets rotated.
34+
LogMaxSize int `mapstructure:"log_maxsize"`
35+
// LogMaxAge is the maximum number of days to retain old log files
36+
// based on the timestamp encoded in their filename. Note that a
37+
// day is defined as 24 hours and may not exactly correspond to
38+
// calendar days due to daylight savings, leap seconds, etc. The
39+
// default is not to remove old log files based on age.
40+
LogMaxAge int `mapstructure:"log_maxage"`
41+
// LogMaxBackups is the maximum number of old log files to retain.
42+
// The default is to retain all old log files (though LogMaxAge may
43+
// still cause them to get deleted).
44+
LogMaxBackups int `mapstructure:"log_maxbackups"`
45+
// ListenInterface is a network interface the IP address
46+
// should be found on to bind http server socket.
47+
ListenInterface string `mapstructure:"listen_interface"`
48+
// RunDir is a path to directory that stores various instance
49+
// runtime artifacts like console socket, PID file, etc.
50+
RunDir string `mapstructure:"run_dir" yaml:"run_dir"`
51+
}

0 commit comments

Comments
 (0)