Added parrot service

This commit is contained in:
Darius klein 2025-07-20 18:46:55 +02:00
parent f54c2a1b70
commit 6ace6a7611
19 changed files with 200 additions and 9 deletions

View File

@ -0,0 +1,45 @@
package service
import (
"context"
"github.com/DariusKlein/kleinCommand/commands/service/subcommands"
"github.com/urfave/cli/v3"
)
// Category service
func Category() *cli.Command {
return &cli.Command{
Name: "service",
Usage: "commands for starting, stopping and communicating with services",
Action: Action,
Commands: commands(),
HideHelpCommand: true,
}
}
// commands for service Category
func commands() []*cli.Command {
return []*cli.Command{
parrot(),
}
}
// Action show help command if no sub commands are given for Category
func Action(context context.Context, c *cli.Command) error {
return cli.ShowSubcommandHelp(c)
}
// parrot sub-category of service Category
func parrot() *cli.Command {
return &cli.Command{
Name: "parrot",
Usage: "commands for interacting with parrot service",
Action: Action,
Commands: []*cli.Command{
subcommands.StartParrotService(),
subcommands.StopParrotService(),
subcommands.Talk(),
},
HideHelpCommand: true,
}
}

View File

@ -0,0 +1,21 @@
package subcommands
import (
"context"
"github.com/DariusKlein/kleinCommand/services"
"github.com/urfave/cli/v3"
)
// StartParrotService Command
func StartParrotService() *cli.Command {
return &cli.Command{
Name: "start",
Usage: "start parrot service",
Action: startParrotServiceAction,
}
}
// startServiceTemplateAction logic for StartServiceTemplate
func startParrotServiceAction(context context.Context, c *cli.Command) error {
return services.RunParrotService()
}

View File

@ -0,0 +1,36 @@
package subcommands
import (
"context"
"github.com/DariusKlein/kleinCommand/common"
"github.com/urfave/cli/v3"
"log/slog"
)
// StopParrotService Command
func StopParrotService() *cli.Command {
return &cli.Command{
Name: "stop",
Usage: "stop parrot service",
Action: stopParrotServiceAction,
}
}
// templateAction logic for Template
func stopParrotServiceAction(context context.Context, c *cli.Command) error {
conn, err := common.GetSocketConnection(common.ParrotServiceSocketPath)
if err != nil {
slog.ErrorContext(context, err.Error())
return err
}
defer conn.Close()
// Send the shutdown command.
_, err = conn.Write([]byte("shutdown\n"))
if err != nil {
slog.ErrorContext(context, err.Error())
return err
}
return nil
}

View File

@ -0,0 +1,49 @@
package subcommands
import (
"bufio"
"context"
"github.com/DariusKlein/kleinCommand/common"
"github.com/urfave/cli/v3"
"log"
"os"
)
// Talk Command
func Talk() *cli.Command {
return &cli.Command{
Name: "talk",
Usage: "talk with parrot",
Action: templateAction,
ArgsUsage: "send arg as message to parrot",
}
}
// templateAction logic for Template
func templateAction(context context.Context, c *cli.Command) error {
conn, err := common.GetSocketConnection(common.ParrotServiceSocketPath)
if err != nil {
return err
}
defer conn.Close()
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
common.CatchInterrupt(func() {
conn.Close()
log.Fatal("Closed connection")
})
for scanner.Scan() {
if _, err = conn.Write([]byte(scanner.Text() + "\n")); err != nil {
return err
}
response := make([]byte, 1024)
if _, err = conn.Read(response); err != nil {
return err
}
log.Println("Response:", string(response))
}
return nil
}

View File

@ -1,3 +1,4 @@
package common package common
const ExampleServiceName = "exampleService" const ExampleServiceName = "exampleService"
const ParrotServiceName = "parrotService"

View File

@ -1,12 +1,18 @@
package common package common
import ( import (
"net"
"os" "os"
"path/filepath" "path/filepath"
) )
var ExampleServiceSocketPath = GetSocketPath(ExampleServiceName) var ExampleServiceSocketPath = GetSocketPath(ExampleServiceName)
var ParrotServiceSocketPath = GetSocketPath(ParrotServiceName)
func GetSocketPath(serviceName string) string { func GetSocketPath(serviceName string) string {
return filepath.Join(os.TempDir(), serviceName+".sock") return filepath.Join(os.TempDir(), serviceName+".sock")
} }
func GetSocketConnection(socketPath string) (net.Conn, error) {
return net.Dial("unix", socketPath)
}

View File

@ -3,4 +3,5 @@ go 1.24.4
use ( use (
. .
services/example services/example
services/parrot
) )

View File

@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"github.com/DariusKlein/kleinCommand/commands/config" "github.com/DariusKlein/kleinCommand/commands/config"
"github.com/DariusKlein/kleinCommand/commands/service"
"github.com/DariusKlein/kleinCommand/commands/templateCommand" "github.com/DariusKlein/kleinCommand/commands/templateCommand"
"github.com/DariusKlein/kleinCommand/common" "github.com/DariusKlein/kleinCommand/common"
"github.com/urfave/cli/v3" "github.com/urfave/cli/v3"
@ -37,6 +38,7 @@ func main() {
Commands: []*cli.Command{ Commands: []*cli.Command{
config.Category(), config.Category(),
templateCommand.Category(), templateCommand.Category(),
service.Category(),
}, },
} }

View File

@ -10,7 +10,7 @@ import (
"time" "time"
) )
func BaseService(socketPath string, logic func(string)) { func BaseService(socketPath string, logic func(string, net.Conn)) {
// Remove socket path on os.Interrupt and syscall.SIGTERM // Remove socket path on os.Interrupt and syscall.SIGTERM
common.CatchInterrupt(func() { common.CatchInterrupt(func() {
os.Remove(socketPath) os.Remove(socketPath)
@ -70,7 +70,7 @@ func BaseService(socketPath string, logic func(string)) {
common.DeleteSelf() common.DeleteSelf()
} }
func handleConnection(conn net.Conn, logic func(string), listener net.Listener) { func handleConnection(conn net.Conn, logic func(string, net.Conn), listener net.Listener) {
defer conn.Close() defer conn.Close()
scanner := bufio.NewScanner(conn) scanner := bufio.NewScanner(conn)
@ -81,7 +81,7 @@ func handleConnection(conn net.Conn, logic func(string), listener net.Listener)
log.Println("Shutdown command received, exiting.") log.Println("Shutdown command received, exiting.")
listener.Close() listener.Close()
} else { } else {
logic(input) logic(input, conn)
} }
} }
} }

Binary file not shown.

Binary file not shown.

BIN
services/binaries/parrotService Executable file

Binary file not shown.

Binary file not shown.

View File

@ -3,15 +3,11 @@ package main
import ( import (
"github.com/DariusKlein/kleinCommand/common" "github.com/DariusKlein/kleinCommand/common"
"github.com/DariusKlein/kleinCommand/services" "github.com/DariusKlein/kleinCommand/services"
"net"
) )
var socketPath = common.ExampleServiceSocketPath var socketPath = common.ExampleServiceSocketPath
func main() { func main() {
services.BaseService(socketPath, func(command string) { services.BaseService(socketPath, func(command string, conn net.Conn) {})
switch command {
case "example\n":
}
})
} }

View File

@ -3,6 +3,7 @@
package services package services
//go:generate go build -o binaries/ ./example //go:generate go build -o binaries/ ./example
//go:generate go build -o binaries/ ./parrot
import ( import (
_ "embed" _ "embed"
@ -14,6 +15,9 @@ import (
//go:embed binaries/exampleService //go:embed binaries/exampleService
var exampleService []byte var exampleService []byte
//go:embed binaries/parrotService
var parrotService []byte
func runService(name string, file []byte) error { func runService(name string, file []byte) error {
tempFile, err := os.CreateTemp("", name) tempFile, err := os.CreateTemp("", name)
if err != nil { if err != nil {

3
services/parrot/go.mod Normal file
View File

@ -0,0 +1,3 @@
module parrotService
go 1.24.4

19
services/parrot/main.go Normal file
View File

@ -0,0 +1,19 @@
package main
import (
"github.com/DariusKlein/kleinCommand/common"
"github.com/DariusKlein/kleinCommand/services"
"log"
"net"
)
var socketPath = common.ParrotServiceSocketPath
func main() {
services.BaseService(socketPath, func(command string, conn net.Conn) {
_, err := conn.Write([]byte(command))
if err != nil {
log.Println(err.Error())
}
})
}

View File

@ -7,3 +7,7 @@ import (
func RunExampleService() error { func RunExampleService() error {
return runService(common.ExampleServiceName, exampleService) return runService(common.ExampleServiceName, exampleService)
} }
func RunParrotService() error {
return runService(common.ParrotServiceName, parrotService)
}

View File

@ -3,6 +3,7 @@
package services package services
//go:generate go build -o binaries/ ./example //go:generate go build -o binaries/ ./example
//go:generate go build -o binaries/ ./parrot
import ( import (
_ "embed" _ "embed"
@ -14,6 +15,9 @@ import (
//go:embed binaries/exampleService.exe //go:embed binaries/exampleService.exe
var exampleService []byte var exampleService []byte
//go:embed binaries/parrotService.exe
var parrotService []byte
func runService(name string, file []byte) error { func runService(name string, file []byte) error {
executableName := name + ".exe" executableName := name + ".exe"
tempFile, err := os.CreateTemp("", executableName) tempFile, err := os.CreateTemp("", executableName)