create instruction with common interface for all available commands + loader (reader.go)

This commit is contained in:
xdrm-brackets 2018-11-08 13:41:07 +01:00
parent ee73fee310
commit 9f1d2923ba
8 changed files with 274 additions and 0 deletions

View File

@ -0,0 +1,48 @@
package instruction
import (
"fmt"
"strings"
)
type config struct {
// File is the path to the file
File string
// Path is the configuration field path
Path []string
// Value if the value to add or update
Value string
}
func (d *config) Build(_args string) error {
// 1. extract action (sub command)
split := strings.SplitN(_args, " ", 2)
// 2. check path
if len(split) < 2 {
return fmt.Errorf("missing configuration path")
}
// 3. check path separator
splitPath := strings.Split(split[0], "@")
if len(splitPath) > 2 {
return fmt.Errorf("invalid path (additional '@'?)")
}
d.File = splitPath[0]
if len(splitPath) > 1 { // add field path only if set
d.Path = strings.Split(splitPath[1], ".")
}
// add value
d.Value = split[1]
return nil
}
func (d config) Exec(ctx ExecutionContext) ([]byte, error) {
return nil, nil
}

View File

@ -0,0 +1,21 @@
package instruction
import (
"git.xdrm.io/xdrm-brackets/nix-amer/internal/cnf"
"git.xdrm.io/xdrm-brackets/nix-amer/internal/pkg"
"git.xdrm.io/xdrm-brackets/nix-amer/internal/ser"
)
// T is the instruction common interface
type T interface {
// Build the instruction with input arguments
Build(string) error
// Exec the given instruction
Exec(ExecutionContext) ([]byte, error)
}
type ExecutionContext struct {
PackageManager pkg.PackageManager
Configuration cnf.ConfigurationFormat
ServiceManager ser.ServiceManager
}

View File

@ -0,0 +1,31 @@
package instruction
import (
"fmt"
"strings"
)
type delete struct {
Packages []string
}
func (d *delete) Build(_args string) error {
d.Packages = strings.Split(_args, " ")
return nil
}
func (d delete) Exec(ctx ExecutionContext) ([]byte, error) {
// delete all packages
for _, pkg := range d.Packages {
err := ctx.PackageManager.Remove(pkg)
if err != nil {
return nil, fmt.Errorf("cannot delete '%s' | %s", pkg, err)
}
}
return nil, nil
}

View File

@ -0,0 +1,8 @@
package instruction
import (
"errors"
)
var ErrInvalidSyntax = errors.New("invalid instruction format")
var ErrUnknownInstruction = errors.New("unknown instruction")

View File

@ -0,0 +1,31 @@
package instruction
import (
"fmt"
"strings"
)
type install struct {
Packages []string
}
func (d *install) Build(_args string) error {
d.Packages = strings.Split(_args, " ")
return nil
}
func (d install) Exec(ctx ExecutionContext) ([]byte, error) {
// install all packages
for _, pkg := range d.Packages {
err := ctx.PackageManager.Install(pkg)
if err != nil {
return nil, fmt.Errorf("cannot install '%s' | %s", pkg, err)
}
}
return nil, nil
}

View File

@ -0,0 +1,49 @@
package instruction
import (
"strings"
)
// Parse from a raw line
func Parse(raw string) (T, error) {
// 1. format (trim + split first space)
raw = strings.Trim(raw, " \t\n")
cmd := strings.SplitN(raw, " ", 2)
cmd[0] = strings.Trim(cmd[0], " \t")
cmd[1] = strings.Trim(cmd[1], " \t")
// 2. fail if invalid base syntax 'cmd args...'
// where command is 3 letters
if len(cmd) < 2 || len(cmd[0]) < 3 || cmd[0][1] == ' ' {
return nil, ErrInvalidSyntax
}
// 3. Extract instruction type
switch cmd[0] {
case "ins":
i := &install{}
err := i.Build(cmd[1])
return i, err
case "del":
i := &delete{}
err := i.Build(cmd[1])
return i, err
case "upd":
i := &update{}
err := i.Build(cmd[1])
return i, err
case "ser":
i := &service{}
err := i.Build(cmd[1])
return i, err
case "cnf":
i := &config{}
err := i.Build(cmd[1])
return i, err
default:
return nil, ErrUnknownInstruction
}
// return nil, nil
}

View File

@ -0,0 +1,58 @@
package instruction
import (
"fmt"
"strings"
)
var actions = []string{"enable", "disable", "start", "stop", "reload", "restart"}
type service struct {
Action string
Services []string
}
func (d *service) Build(_args string) error {
// 1. extract action (sub command)
split := strings.Split(_args, " ")
// 2. check action
if len(split) < 2 {
return fmt.Errorf("invalid syntax, missing action or unit")
}
// 3. fail if unknown action
known := false
for _, act := range actions {
if split[0] == act {
known = true
break
}
}
if !known {
return fmt.Errorf("unknown action '%s'", split[0])
}
d.Action = split[0]
// 4. Store services
d.Services = split[1:]
return nil
}
func (d service) Exec(ctx ExecutionContext) ([]byte, error) {
// delete all packages
for _, service := range d.Services {
if err := ctx.ServiceManager.Exec(d.Action, service); err != nil {
return nil, fmt.Errorf("cannot %s '%s' | %s", d.Action, service, err)
}
}
return nil, nil
}

View File

@ -0,0 +1,28 @@
package instruction
import (
"fmt"
)
type update struct{}
func (d *update) Build(_args string) error {
return nil
}
func (d update) Exec(ctx ExecutionContext) ([]byte, error) {
// fetch packages
err := ctx.PackageManager.Fetch()
if err != nil {
return nil, fmt.Errorf("cannot fetch packages | %s", err)
}
// update packages
err = ctx.PackageManager.Upgrade()
if err != nil {
return nil, fmt.Errorf("cannot upgrade | %s", err)
}
return nil, nil
}