diff --git a/cmd/ectl/go.mod b/cmd/ectl/go.mod index 097f73a..529f147 100644 --- a/cmd/ectl/go.mod +++ b/cmd/ectl/go.mod @@ -2,4 +2,7 @@ module ectl go 1.23.4 -require rsc.io/getopt v0.0.0-20170811000552-20be20937449 // indirect +require ( + gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/getopt v0.0.0-20170811000552-20be20937449 // indirect +) diff --git a/cmd/ectl/go.sum b/cmd/ectl/go.sum index 5894729..50f68f8 100644 --- a/cmd/ectl/go.sum +++ b/cmd/ectl/go.sum @@ -1,2 +1,5 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= rsc.io/getopt v0.0.0-20170811000552-20be20937449 h1:UukjJOsjQH0DIuyyrcod6CXHS6cdaMMuJmrt+SN1j4A= rsc.io/getopt v0.0.0-20170811000552-20be20937449/go.mod h1:dhCdeqAxkyt5u3/sKRkUXuHaMXUu1Pt13GTQAM2xnig= diff --git a/cmd/ectl/main.go b/cmd/ectl/main.go index 4272693..6a39528 100644 --- a/cmd/ectl/main.go +++ b/cmd/ectl/main.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + "gopkg.in/yaml.v3" "log" "net" "os" @@ -127,6 +128,102 @@ func main() { } fmt.Println("Service restarted successfully!") return + } else if flag.Args()[1] == "enable" { + // Check if service exists + found := false + entries, err := os.ReadDir(path.Join(sysconfdir, "esvm/services/")) + if err != nil { + log.Fatalf("Could not enable service! Error: %s\n", err) + } + type minimalServiceStruct struct { + Name string `yaml:"name"` + } + for _, entry := range entries { + if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".esv") { + continue + } + + bytes, err := os.ReadFile(path.Join(sysconfdir, "esvm/services", entry.Name())) + if err != nil { + log.Fatalf("Could not enable service! Error: %s\n", err) + } + + sv := minimalServiceStruct{Name: ""} + err = yaml.Unmarshal(bytes, &sv) + if err != nil { + log.Fatalf("Could not enable service! Error: %s\n", err) + } + + if sv.Name == flag.Args()[2] { + found = true + break + } + } + if !found { + log.Fatalf("Service does not exist!") + } + + if _, err := os.Stat(path.Join(sysconfdir, "esvm/enabled_services")); err != nil { + err := os.WriteFile(path.Join(sysconfdir, "esvm/enabled_services"), []byte(flag.Args()[2]+"\n"), 0644) + if err != nil { + log.Fatalf("Could not enable service! Error: %s\n", err) + } + return + } + + file, err := os.ReadFile(path.Join(sysconfdir, "esvm/enabled_services")) + if err != nil { + log.Fatalf("Could not enable service! Error: %s\n", err) + } + for _, line := range strings.Split(string(file), "\n") { + if strings.TrimSpace(line) == flag.Args()[2] { + fmt.Println("Service is already enabled!") + return + } + } + + err = os.WriteFile(path.Join(sysconfdir, "esvm/enabled_services"), []byte(string(file)+flag.Args()[2]+"\n"), 0644) + if err != nil { + log.Fatalf("Could not enable service! Error: %s\n", err) + } + + fmt.Printf("Service (%s) has been enabled!\n", flag.Args()[2]) + return + } else if flag.Args()[1] == "disable" { + if _, err := os.Stat(path.Join(sysconfdir, "esvm/enabled_services")); err != nil { + fmt.Println("Service is already disabled!") + return + } + + file, err := os.ReadFile(path.Join(sysconfdir, "esvm/enabled_services")) + if err != nil { + log.Fatalf("Could not disable service! Error: %s\n", err) + } + + lines := strings.Split(string(file), "\n") + found := false + for i := len(lines) - 1; i >= 0; i-- { + line := strings.TrimSpace(lines[i]) + if strings.TrimSpace(line) == flag.Args()[2] { + lines = append(lines[:i], lines[i+1:]...) + found = true + } else if strings.TrimSpace(line) == "" { + lines = append(lines[:i], lines[i+1:]...) + } + } + + if !found { + fmt.Println("Service is already disabled!") + return + } + + err = os.WriteFile(path.Join(sysconfdir, "esvm/enabled_services"), []byte(strings.Join(lines, "\n")+"\n"), 0644) + if err != nil { + log.Fatalf("Could not disable service! Error: %s\n", err) + } + + fmt.Printf("Service (%s) has been disabled!\n", flag.Args()[2]) + return } else if flag.Args()[1] == "status" { flag.Args()[2] = strings.TrimSuffix(flag.Args()[2], ".esv") if _, err := os.Stat(path.Join(sysconfdir, "esvm/services/", flag.Args()[2]+".esv")); err != nil { diff --git a/cmd/esvm/main.go b/cmd/esvm/main.go index ee44ec6..aeef7ed 100644 --- a/cmd/esvm/main.go +++ b/cmd/esvm/main.go @@ -11,6 +11,7 @@ import ( "os/exec" "os/signal" "path" + "slices" "strconv" "strings" "syscall" @@ -49,6 +50,7 @@ var runtimeServiceDir string var serviceConfigDir string var Services = make([]EnitService, 0) +var EnabledServices = make([]string, 0) var logger *log.Logger var socket net.Listener @@ -154,6 +156,12 @@ func Init() { continue } + for _, sv := range Services { + if sv.Name == service.Name { + logger.Printf("Service with name (%s) has already been initialized!", service.Name) + } + } + switch service.Type { case "simple", "background": default: @@ -185,15 +193,28 @@ func Init() { } } - // Get services that meet their dependencies + // Get enabled services + if _, err := os.Stat(path.Join(serviceConfigDir, "enabled_services")); err == nil { + file, err := os.ReadFile(path.Join(serviceConfigDir, "enabled_services")) + if err != nil { + return + } + for _, line := range strings.Split(string(file), "\n") { + if line != "" { + EnabledServices = append(EnabledServices, line) + } + } + } + + // Get enabled services that meet their dependencies servicesWithMetDepends := make([]EnitService, 0) for _, service := range Services { - if len(service.GetUnmetDependencies()) == 0 { + if slices.Contains(EnabledServices, service.Name) && len(service.GetUnmetDependencies()) == 0 { servicesWithMetDepends = append(servicesWithMetDepends, service) } } - // Loop until all services have started or timed out + // Loop until all enabled services have started or timed out for start := time.Now(); time.Since(start) < 60*time.Second; { if len(servicesWithMetDepends) == 0 { break