Skip to content

Commit

Permalink
added service manager and support for systemd and sysvinit service ma…
Browse files Browse the repository at this point in the history
…nagement
  • Loading branch information
darki73 committed Sep 19, 2023
1 parent 06f3866 commit 2dac7d1
Show file tree
Hide file tree
Showing 13 changed files with 1,362 additions and 230 deletions.
323 changes: 93 additions & 230 deletions cmd/service.go

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"github.com/darki73/goflaresync/pkg/configuration"
"github.com/darki73/goflaresync/pkg/log"
"github.com/darki73/goflaresync/pkg/service"
"github.com/darki73/goflaresync/pkg/watcher"
"github.com/spf13/cobra"
)
Expand All @@ -17,6 +18,21 @@ var startCmd = &cobra.Command{
log.Fatal(err.Error())
}

manager := service.NewManager()
systemManager := manager.GetSystemManager()
if systemManager != nil {
if err := systemManager.GetProcessIdentifierHandler().HandleApplicationStart(); err != nil {
log.Fatal(err.Error())
}

defer func(handler *service.ProcessIdentifierHandler) {
err := handler.HandleApplicationStop()
if err != nil {
log.Fatal(err.Error())
}
}(systemManager.GetProcessIdentifierHandler())
}

instance := watcher.New()
if err := instance.Start(); err != nil {
log.Fatal(err.Error())
Expand Down
32 changes: 32 additions & 0 deletions cmd/stop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"github.com/darki73/goflaresync/pkg/log"
"github.com/darki73/goflaresync/pkg/service"
"github.com/spf13/cobra"
)

// stopCmd represents the stop command.
var stopCmd = &cobra.Command{
Use: "stop",
Short: "Stops the service",
Long: "Stops the service",
Run: func(cmd *cobra.Command, args []string) {
if err := initializeConfiguration(); err != nil {
log.Fatal(err.Error())
}

manager := service.NewManager()
systemManager := manager.GetSystemManager()
if systemManager != nil {
if err := systemManager.GetProcessIdentifierHandler().HandleApplicationStop(); err != nil {
log.Fatal(err.Error())
}
}
},
}

// init initializes the command.
func init() {
rootCmd.AddCommand(stopCmd)
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ module github.com/darki73/goflaresync
go 1.19

require (
github.com/Code-Hex/dd v1.1.0
github.com/fsnotify/fsnotify v1.6.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/spf13/viper v1.16.0
)

require (
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/spf13/afero v1.9.5 // indirect
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Code-Hex/dd v1.1.0 h1:VEtTThnS9l7WhpKUIpdcWaf0B8Vp0LeeSEsxA1DZseI=
github.com/Code-Hex/dd v1.1.0/go.mod h1:VaMyo/YjTJ3d4qm/bgtrUkT2w+aYwJ07Y7eCWyrJr1w=
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
Expand All @@ -50,6 +54,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down Expand Up @@ -136,6 +142,10 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
Expand Down Expand Up @@ -311,6 +321,8 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
Expand Down
20 changes: 20 additions & 0 deletions pkg/debug/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package debug

import (
"github.com/Code-Hex/dd/p"
"github.com/darki73/goflaresync/pkg/log"
"os"
)

// Dump dumps the arguments.
func Dump(args ...interface{}) {
if _, err := p.P(args...); err != nil {
log.Fatalf("failed to dump: %s", err.Error())
}
}

// DieAndDump dumps the arguments and exits.
func DieAndDump(args ...interface{}) {
Dump(args...)
os.Exit(0)
}
27 changes: 27 additions & 0 deletions pkg/helpers/application.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package helpers

import (
"os"
"path/filepath"
"strings"
)

// GetExecutableDirectory returns the directory containing the executable.
func GetExecutableDirectory() (string, error) {
executablePath, err := os.Executable()
if err != nil {
return "", err
}

executableDirectory := filepath.Dir(executablePath)
return executableDirectory, nil
}

// GetExecutableName returns the name of the executable.
func GetExecutableName() string {
executableName := filepath.Base(os.Args[0])
if strings.Contains(executableName, ".") {
executableName = strings.Split(executableName, ".")[0]
}
return executableName
}
12 changes: 12 additions & 0 deletions pkg/helpers/directory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package helpers

import "os"

// IsDirectoryExists returns a boolean value indicating whether the directory exists.
func IsDirectoryExists(directoryPath string) bool {
info, err := os.Stat(directoryPath)
if os.IsNotExist(err) {
return false
}
return info.IsDir()
}
120 changes: 120 additions & 0 deletions pkg/service/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package service

import (
"github.com/darki73/goflaresync/pkg/helpers"
"github.com/darki73/goflaresync/pkg/log"
"os"
"path"
"strings"
)

// InitializationSystemManager is the initialization system manager.
type InitializationSystemManager interface {
// GetServiceTemplate returns the service template.
GetServiceTemplate() (string, error)
// GetServicePath returns the service path.
GetServicePath() string
// GetProcessIdentifierHandler returns the process identifier handler.
GetProcessIdentifierHandler() *ProcessIdentifierHandler
// CreateService creates the service.
CreateService() error
// DeleteService deletes the service.
DeleteService() error
// EnableService enables the service.
EnableService() error
// DisableService disables the service.
DisableService() error
// StartService starts the service.
StartService() error
// StopService stops the service.
StopService() error
// RestartService restarts the service.
RestartService() error
// ReloadManager reloads the manager.
ReloadManager() error
// IsRunningAsRoot checks if the application is running as root.
IsRunningAsRoot()
// IsServiceExists checks if the service exists.
IsServiceExists() bool
// IsServiceEnabled checks if the service is enabled.
IsServiceEnabled() (bool, error)
// IsServiceRunning checks if the service is running.
IsServiceRunning() (bool, error)
}

// mergeLogFields merges the log fields.
func mergeLogFields(fields log.FieldsMap) log.FieldsMap {
defaultFields := log.FieldsMap{
"source": "service",
}

if fields == nil {
return defaultFields
}

for key, value := range defaultFields {
fields[key] = value
}

return fields
}

// logDebug logs a debug message.
func logDebug(message string, fields log.FieldsMap) {
log.DebugWithFields(message, mergeLogFields(fields))
}

// logDebugf logs a debug message.
func logDebugf(message string, fields log.FieldsMap, args ...interface{}) {
log.DebugfWithFields(message, mergeLogFields(fields), args...)
}

// logInfo logs an info message.
func logInfo(message string, fields log.FieldsMap) {
log.InfoWithFields(message, mergeLogFields(fields))
}

// logInfof logs an info message.
func logInfof(message string, fields log.FieldsMap, args ...interface{}) {
log.InfofWithFields(message, mergeLogFields(fields), args...)
}

// applicationName returns the name of the application.
func applicationName() string {
return helpers.GetExecutableName()
}

// applicationFullPath returns the full path of the application.
func applicationFullPath() (string, error) {
directory, err := helpers.GetExecutableDirectory()
if err != nil {
return "", err
}
return path.Join(directory, applicationName()), nil
}

// combineSlices combines the slices.
func combineSlices(slices ...[]string) string {
var combined []string

for _, slice := range slices {
combined = append(combined, slice...)
}

return strings.Join(combined, "\n")
}

// isRunningAsRoot checks if the application is running as root.
func isRunningAsRoot() {
if !helpers.IsRoot() {
log.Fatal("this command must be run as root")
}
}

// isServiceExists checks if the service exists.
func isServiceExists(baseDirectory string, serviceName string) bool {
if _, err := os.Stat(path.Join(baseDirectory, serviceName)); err != nil {
return false
}
return true
}
Loading

0 comments on commit 2dac7d1

Please sign in to comment.