diff --git a/migrate.go b/cmd_migrate.go similarity index 100% rename from migrate.go rename to cmd_migrate.go diff --git a/model.go b/cmd_model.go similarity index 100% rename from model.go rename to cmd_model.go diff --git a/root.go b/cmd_root.go similarity index 97% rename from root.go rename to cmd_root.go index f951169..09ed9aa 100644 --- a/root.go +++ b/cmd_root.go @@ -17,6 +17,7 @@ var cfgFile string var ( GroupRoutes = dig.Group("routes") GroupGrpcServer = dig.Group("grpc_server_services") + GroupCommand = dig.Group("command_services") ) func init() { @@ -39,6 +40,7 @@ func Serve(providers container.Providers, opts ...Option) error { withMigrationCommand(rootCmd) withModelCommand(rootCmd) withSeederCommand(rootCmd) + withServiceInstall(rootCmd) return rootCmd.Execute() } diff --git a/seeder.go b/cmd_seeder.go similarity index 100% rename from seeder.go rename to cmd_seeder.go diff --git a/cmd_service.go b/cmd_service.go new file mode 100644 index 0000000..b19d20a --- /dev/null +++ b/cmd_service.go @@ -0,0 +1,80 @@ +package atom + +import ( + "bytes" + "fmt" + "html/template" + "os" + "os/exec" + + "github.com/rogeecn/atom/container" + + "github.com/spf13/cobra" +) + +var enableService bool + +type ServiceVars struct { + ExecStart string + Description string + WantedBy string +} + +func withServiceInstall(rootCmd *cobra.Command) *cobra.Command { + serviceTpl := `[Unit] +Description={{.Description}} + +[Service] +Type=simple +ExecStart={{.ExecStart}} + +[Install] +WantedBy={{.WantedBy}}` + var serviceCmd = &cobra.Command{ + Use: "service", + Short: "install linux service", + RunE: func(cmd *cobra.Command, args []string) error { + return container.Container.Invoke(func() error { + tpl, err := template.New("service").Parse(serviceTpl) + if err != nil { + return err + } + + exe, err := os.Executable() + if err != nil { + return err + } + + vars := ServiceVars{ + ExecStart: exe, + Description: rootCmd.Short, + WantedBy: "multi-user.target", + } + + tplWriter := bytes.NewBuffer(nil) + if err := tpl.Execute(tplWriter, vars); err != nil { + return err + } + + filename := fmt.Sprintf("/etc/systemd/system/%s.service", rootCmd.Use) + if err := os.WriteFile(filename, tplWriter.Bytes(), os.ModePerm); err != nil { + return err + } + + if enableService { + b, err := exec.Command("sudo", "systemctl", "enable", rootCmd.Use, "--now").CombinedOutput() + if err != nil { + return fmt.Errorf("%s: %s", err, string(b)) + } + } + + return nil + }) + }, + } + + rootCmd.AddCommand(serviceCmd) + serviceCmd.Flags().BoolVar(&enableService, "enable", true, "enable service after install") + + return rootCmd +} diff --git a/go.sum b/go.sum index 9f2a0dd..808bc64 100644 --- a/go.sum +++ b/go.sum @@ -207,6 +207,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -360,6 +361,7 @@ github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcD github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= diff --git a/services/command.go b/services/command.go new file mode 100644 index 0000000..e649bd0 --- /dev/null +++ b/services/command.go @@ -0,0 +1,27 @@ +package services + +import ( + "github.com/rogeecn/atom/container" + "go.uber.org/dig" +) + +type CommandService interface { + Register() + Execute() error +} + +type Command struct { + dig.In + + Commands []CommandService `group:"command_services"` +} + +func ServeCommand(f func() error) error { + return container.Container.Invoke(func(command Command) error { + for _, cmd := range command.Commands { + cmd.Register() + } + + return f() + }) +}