Skip to content

Commit

Permalink
feat: retrieve and update service
Browse files Browse the repository at this point in the history
  • Loading branch information
DeeStarks committed Aug 10, 2022
1 parent a78403e commit 4131e0a
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 31 deletions.
103 changes: 79 additions & 24 deletions app/cli/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ type ServiceProcess struct {
}

// List running services
func (ac *ServiceCommand) ListRunning() {
domainPort := port.NewDomainPort(ac.defaultDB)
func (c *ServiceCommand) ListRunning() {
domainPort := port.NewDomainPort(c.defaultDB)
processes, err := domainPort.ServiceProcesses().RetrieveRunning()
if err != nil {
fmt.Println("Error retrieve running services:", err)
Expand All @@ -47,9 +47,9 @@ func (ac *ServiceCommand) ListRunning() {

// Draw table to list processes
t := table.New(os.Stdout)
t.SetDividers(table.UnicodeRoundedDividers)
t.SetDividers(table.UnicodeDividers)

t.SetHeaders("PID", "NAME", "TYPE", "LISTENERS", "ROOT", "CLIENT", "TUNNELLED", "CREATED")
t.SetHeaders("NAME", "TYPE", "LISTENERS", "ROOT", "CLIENT", "TUNNELLED", "CREATED")
for _, p := range processes {
created_at := utils.TimeAgo(p.CreatedAt, time.Now().Unix())
listeners := strings.Join(p.Listeners, ", ")
Expand All @@ -61,7 +61,8 @@ func (ac *ServiceCommand) ListRunning() {
}

t.AddRow(
string(p.Pid), p.Name, p.Type, listeners, p.RootDirectory,
p.Name, p.Type, utils.TruncateString(listeners, 20),
utils.TruncateString(p.RootDirectory, 20),
p.ClientAddress, tunnelled, created_at,
)
}
Expand All @@ -70,8 +71,8 @@ func (ac *ServiceCommand) ListRunning() {
}

// List all services
func (ac *ServiceCommand) ListAll() {
domainPort := port.NewDomainPort(ac.defaultDB)
func (c *ServiceCommand) ListAll() {
domainPort := port.NewDomainPort(c.defaultDB)
processes, err := domainPort.ServiceProcesses().RetrieveAll()
if err != nil {
fmt.Println("Error retrieving services:", err)
Expand All @@ -80,9 +81,9 @@ func (ac *ServiceCommand) ListAll() {

// Draw table to list processes
t := table.New(os.Stdout)
t.SetDividers(table.UnicodeRoundedDividers)
t.SetDividers(table.UnicodeDividers)

t.SetHeaders("PID", "NAME", "STATUS", "TYPE", "LISTENERS", "ROOT", "CLIENT", "TUNNELLED", "CREATED")
t.SetHeaders("NAME", "STATUS", "TYPE", "LISTENERS", "ROOT", "CLIENT", "TUNNELLED", "CREATED")
for _, p := range processes {
created_at := utils.TimeAgo(p.CreatedAt, time.Now().Unix())
listeners := strings.Join(p.Listeners, ", ")
Expand All @@ -98,19 +99,20 @@ func (ac *ServiceCommand) ListAll() {
}

t.AddRow(
string(p.Pid), p.Name, status, p.Type, listeners, p.RootDirectory,
p.Name, status, p.Type, utils.TruncateString(listeners, 20),
utils.TruncateString(p.RootDirectory, 20),
p.ClientAddress, tunnelled, created_at,
)
}
t.Render()
}

// Add new service
func (ac *ServiceCommand) Add(filepath string) {
func (c *ServiceCommand) Add(filepath string, update bool) {
// Ensure the file exists
f, err := os.Open(filepath)
if err != nil {
fmt.Println("Could not add new service; \"conoid.yml\": File not found")
fmt.Println("No file named: \"conoid.yml\"")
return
}
defer f.Close()
Expand All @@ -129,26 +131,33 @@ func (ac *ServiceCommand) Add(filepath string) {
}

// Ensure service doesn't already exist
domainPort := port.NewDomainPort(ac.defaultDB)
domainPort := port.NewDomainPort(c.defaultDB)
processes, err := domainPort.ServiceProcesses().RetrieveAll()
if err != nil {
fmt.Println("Could not add service:", err)
fmt.Println(err)
return
}

// Check processes' names
var serviceToUpdate string
for _, p := range processes {
if p.Name == validatedConf.Name {
fmt.Printf("Could not add service: an service with name \"%s\" already exists\n", validatedConf.Name)
return
if !update {
fmt.Printf("A service already exists with the name \"%s\"; Use the \"--update\" flag to modify service\n", validatedConf.Name)
return
}

// Store data for update
serviceToUpdate = p.Name
break
}
}

// Convert the configurations to a map type
// First, to json
jsondata, err := json.Marshal(validatedConf)
if err != nil {
fmt.Println("Could not add service:", err)
fmt.Println(err)
return
}
// Now, to map
Expand All @@ -171,15 +180,61 @@ func (ac *ServiceCommand) Add(filepath string) {
mapConf["listeners"] = strings.Join(ss, ", ")
}

// Generate pid, status, and created at
mapConf["pid"] = strings.ReplaceAll(uuid.New().String(), "-", "") // Stripping hyphens
mapConf["status"] = 1
mapConf["created_at"] = time.Now().Unix()
if !update {
// Generate pid, status, and created at
mapConf["pid"] = strings.ReplaceAll(uuid.New().String(), "-", "") // Stripping hyphens
mapConf["status"] = 1
mapConf["created_at"] = time.Now().Unix()

_, err = domainPort.ServiceProcesses().Create(mapConf)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Your service was successfully added. Restart conoid to start accepting request")
} else {
// Updating service
_, err := domainPort.ServiceProcesses().Update(serviceToUpdate, mapConf)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("\"%s\" service was updated. Restart conoid to synchronize update\n", serviceToUpdate)
}
}

_, err = domainPort.ServiceProcesses().Create(mapConf)
// Retrieve details of a servive
func (c *ServiceCommand) Get(name string) {
// Retrieve from db
domainPort := port.NewDomainPort(c.defaultDB)
service, err := domainPort.ServiceProcesses().Get(name)
if err != nil {
fmt.Println("Could not add service:", err)
fmt.Printf("Could not retrieve service: \"%s\"\n", name)
return
}
fmt.Println("Your service was successfully added. Restart conoid to start accepting request")

// Convert booleans to string type
tunnelled := "False"
if service.Tunnelled {
tunnelled = "True"
}
status := "Stopped"
if service.Status {
status = "Running"
}

// Show table
t := table.New(os.Stdout)
t.SetDividers(table.UnicodeDividers)
t.AddRow("NAME", service.Name)
t.AddRow("STATUS", status)
t.AddRow("TYPE", strings.Title(service.Type)+" rendering")
t.AddRow("LISTENING ON", strings.Join(service.Listeners, ", "))
if service.Type == "static" {
t.AddRow("DOCUMENT DIRECTORY", service.RootDirectory)
}
t.AddRow("ALLOWED HOST", service.ClientAddress)
t.AddRow("TUNNELLED", tunnelled)
t.AddRow("CREATED", utils.TimeAgo(service.CreatedAt, time.Now().Unix()))
t.Render()
}
34 changes: 27 additions & 7 deletions cmd/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,31 @@ var (
// Initialize "service" commands
services := cli.NewCLICommands().Services()

// Add new service
if f, _ := flags.GetBool("add"); f {
// Add new service

// Open the app's configuration file "conoid.yml"
wd, _ := os.Getwd()
pathToConf := filepath.Join(wd, "conoid.yml")
// Check if such file exists
if _, err := os.Stat(pathToConf); err != nil {
fmt.Println("A file named \"conoid.yml\" could not be found in the current directory")
fmt.Println("No file named \"conoid.yml\" in the current directory")
return
}
services.Add(pathToConf)
services.Add(pathToConf, false)
return
} else if f, _ := flags.GetBool("update"); f {
// Update existing service

// Open the app's configuration file "conoid.yml"
wd, _ := os.Getwd()
pathToConf := filepath.Join(wd, "conoid.yml")
// Check if such file exists
if _, err := os.Stat(pathToConf); err != nil {
fmt.Println("No file named \"conoid.yml\" in the current directory")
return
}
services.Add(pathToConf, true)
return
}
},
Expand All @@ -52,11 +66,15 @@ var (
// List all Services
if f, _ := flags.GetBool("all"); f {
services.ListAll()
return
} else if f, _ := flags.GetBool("all"); f {
// Retrieve a service
services.ListAll()
} else if f, _ := flags.GetString("name"); f != "" {
services.Get(f)
} else {
// List running services
services.ListRunning()
}

// List only running services
services.ListRunning()
},
}
)
Expand All @@ -65,8 +83,10 @@ func init() {
// serviceCmd
rootCmd.AddCommand(serviceCmd)
serviceCmd.Flags().BoolP("add", "", false, "lookup \"conoid.yml\" file in the current directory and add service")
serviceCmd.Flags().BoolP("update", "", false, "modify service based on \"conoid.yml\"")

// servicePsCmd
serviceCmd.AddCommand(servicePsCmd)
servicePsCmd.Flags().BoolP("all", "a", false, "list all services")
servicePsCmd.Flags().StringP("name", "n", "", "show details of a service")
}
4 changes: 4 additions & 0 deletions domain/ports/processes_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import (
type ProcessesPort interface {
RetrieveRunning() ([]repository.ServiceProcessModel, error)
RetrieveAll() ([]repository.ServiceProcessModel, error)
// Pass data in paramaters to create
Create(map[string]interface{}) (repository.ServiceProcessModel, error)
// Pass the service name and data in paramaters to update
Update(string, map[string]interface{}) (repository.ServiceProcessModel, error)
// Pass the service name to be retrieved
Get(string) (repository.ServiceProcessModel, error)
}

func (p DomainPort) ServiceProcesses() ProcessesPort {
Expand Down
32 changes: 32 additions & 0 deletions domain/repository/processes.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,35 @@ func (p ServiceProcess) Update(name string, data map[string]interface{}) (Servic
// Return result
return process, nil
}

func (p ServiceProcess) Get(name string) (ServiceProcessModel, error) {
var process ServiceProcessModel

// Execute query
query := `
SELECT
pid, name, status, type, listeners,
root_directory, client_address, tunnelled, created_at
FROM processes WHERE name=$1
`

// Handle null values
var listeners, root_directory, client_address sql.NullString
err := p.DB.QueryRow(query, name).Scan(
&process.Pid, &process.Name, &process.Status, &process.Type,
&listeners, &root_directory, &client_address,
&process.Tunnelled, &process.CreatedAt,
)
if err != nil {
return ServiceProcessModel{}, err
}

process.RootDirectory = root_directory.String
process.ClientAddress = client_address.String
// Listeners are stored in the db as strings separated by comma
// we'll split that into slice
process.Listeners = strings.Split(listeners.String, ", ")

// Return result
return process, nil
}

0 comments on commit 4131e0a

Please sign in to comment.