diff --git a/internal/instruction/cnf.go b/internal/instruction/cnf.go new file mode 100644 index 0000000..51facc6 --- /dev/null +++ b/internal/instruction/cnf.go @@ -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 + +} diff --git a/internal/instruction/common.go b/internal/instruction/common.go new file mode 100644 index 0000000..66b383b --- /dev/null +++ b/internal/instruction/common.go @@ -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 +} diff --git a/internal/instruction/del.go b/internal/instruction/del.go new file mode 100644 index 0000000..ad7f1d7 --- /dev/null +++ b/internal/instruction/del.go @@ -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 + +} diff --git a/internal/instruction/errors.go b/internal/instruction/errors.go new file mode 100644 index 0000000..64eaf45 --- /dev/null +++ b/internal/instruction/errors.go @@ -0,0 +1,8 @@ +package instruction + +import ( + "errors" +) + +var ErrInvalidSyntax = errors.New("invalid instruction format") +var ErrUnknownInstruction = errors.New("unknown instruction") diff --git a/internal/instruction/ins.go b/internal/instruction/ins.go new file mode 100644 index 0000000..87919bb --- /dev/null +++ b/internal/instruction/ins.go @@ -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 + +} diff --git a/internal/instruction/reader.go b/internal/instruction/reader.go new file mode 100644 index 0000000..b3fc4ee --- /dev/null +++ b/internal/instruction/reader.go @@ -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 +} diff --git a/internal/instruction/ser.go b/internal/instruction/ser.go new file mode 100644 index 0000000..6a1bb67 --- /dev/null +++ b/internal/instruction/ser.go @@ -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 + +} diff --git a/internal/instruction/upd.go b/internal/instruction/upd.go new file mode 100644 index 0000000..006aa2a --- /dev/null +++ b/internal/instruction/upd.go @@ -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 +}