create os/exec generic interface (internal/exec) with 'Default' wrapping os/exec + make tests do not use it

This commit is contained in:
xdrm-brackets 2018-11-11 21:38:16 +01:00
parent 2901a4edd4
commit 1df8f9df9e
16 changed files with 175 additions and 60 deletions

View File

@ -6,6 +6,27 @@ import (
"testing"
)
func TestNullContext(t *testing.T) {
buffer := bytes.NewBufferString("")
_, err := NewReader(nil, buffer)
if err != ErrNullContext {
t.Fatalf("expected <%s>, got <%v>", ErrNullContext, err)
}
}
func TestIgnoreCommentsAndEmptyLines(t *testing.T) {
ctx, _ := instruction.CreateContext("apt-get", "")
buffer := bytes.NewBufferString("[ some comment ]\n\n \t \n\t \t\n[ other comment after empty lines ]")
r, err := NewReader(ctx, buffer)
if err != nil {
t.Fatalf("unexpected error <%v>", err)
}
if len(r.Content) > 0 {
t.Fatalf("expected no content, got %d instructions", len(r.Content))
}
}
func TestInstructionSyntax(t *testing.T) {
tests := []struct {
File string

12
internal/exec/common.go Normal file
View File

@ -0,0 +1,12 @@
package exec
// Command is the common interface wrapping os/exec.Command() output
type Command interface {
Run() error
Output() ([]byte, error)
}
// Executor is the common interface wrapping os/exec.Command()
type Executor interface {
Command(string, ...string) Command
}

11
internal/exec/os.go Normal file
View File

@ -0,0 +1,11 @@
package exec
import (
osexec "os/exec"
)
type Default struct{}
func (d *Default) Command(cmd string, args ...string) Command {
return osexec.Command(cmd, args...)
}

View File

@ -2,6 +2,7 @@ package instruction
import (
"fmt"
"git.xdrm.io/go/nix-amer/internal/exec"
"git.xdrm.io/go/nix-amer/internal/pkg"
"git.xdrm.io/go/nix-amer/internal/ser"
)
@ -16,8 +17,14 @@ type T interface {
Exec(ExecutionContext) ([]byte, error)
}
// Executor is the common interface to execute commands
type Executor interface {
Execute(...string) error
}
// ExecutionContext contains system-specific drivers to manage the host
type ExecutionContext struct {
ExecContext Executor
PackageManager pkg.PackageManager
ServiceManager ser.ServiceManager
}
@ -42,12 +49,14 @@ func CreateContext(_pkg, _ser string) (*ExecutionContext, error) {
_ser = ser.DefaultManager
}
executor := new(exec.Default)
// 3. load managers
pkg, err := pkg.Load(_pkg)
pkg, err := pkg.Load(_pkg, executor)
if err != nil {
return nil, fmt.Errorf("package manager: %s", err)
}
ser, err := ser.Load(_ser)
ser, err := ser.Load(_ser, executor)
if err != nil {
return nil, fmt.Errorf("service manager: %s", err)
}

View File

@ -1,25 +1,27 @@
package pkg
import (
"os/exec"
)
import "git.xdrm.io/go/nix-amer/internal/exec"
type apk struct{}
type apk struct{ exec exec.Executor }
func (d *apk) SetExecutor(_exec exec.Executor) {
d.exec = _exec
}
func (d apk) Name() string { return "apk" }
func (d apk) Fetch() error {
return exec.Command(d.Name(), "update").Run()
return d.exec.Command(d.Name(), "update").Run()
}
func (d apk) Upgrade() error {
return exec.Command(d.Name(), "upgrade").Run()
return d.exec.Command(d.Name(), "upgrade").Run()
}
func (d apk) Install(_pkg string) error {
return exec.Command(d.Name(), "add", _pkg).Run()
return d.exec.Command(d.Name(), "add", _pkg).Run()
}
func (d apk) Remove(_pkg string) error {
return exec.Command(d.Name(), "del", _pkg).Run()
return d.exec.Command(d.Name(), "del", _pkg).Run()
}

View File

@ -1,40 +1,44 @@
package pkg
import (
"os/exec"
"git.xdrm.io/go/nix-amer/internal/exec"
)
type aptGet struct{}
type aptGet struct{ exec exec.Executor }
func (d *aptGet) SetExecutor(_exec exec.Executor) {
d.exec = _exec
}
func (d aptGet) Name() string { return "apt-get" }
func (d aptGet) Fetch() error {
err := exec.Command(d.Name(), "update").Run()
err := d.exec.Command(d.Name(), "update").Run()
return err
}
func (d aptGet) Upgrade() error {
err := exec.Command(d.Name(), "upgrade").Run()
err := d.exec.Command(d.Name(), "upgrade").Run()
if err != nil {
return err
}
err = exec.Command(d.Name(), "dist-upgrade").Run()
err = d.exec.Command(d.Name(), "dist-upgrade").Run()
if err != nil {
return err
}
exec.Command(d.Name(), "autoremove").Run()
d.exec.Command(d.Name(), "autoremove").Run()
return nil
}
func (d aptGet) Install(_pkg string) error {
err := exec.Command(d.Name(), "install", _pkg).Run()
err := d.exec.Command(d.Name(), "install", _pkg).Run()
return err
}
func (d aptGet) Remove(_pkg string) error {
err := exec.Command(d.Name(), "remove", _pkg).Run()
exec.Command(d.Name(), "autoremove").Run()
err := d.exec.Command(d.Name(), "remove", _pkg).Run()
d.exec.Command(d.Name(), "autoremove").Run()
return err
}

View File

@ -1,10 +1,16 @@
package pkg
import (
"git.xdrm.io/go/nix-amer/internal/exec"
)
// DefaultManager if not empty is the default package-manager to use when missing
var DefaultManager = ""
// PackageManager is the common interface for all package-manager drivers (e.g. `dpkg` for debian-based, `pacman` for arch)
type PackageManager interface {
// SetExecContext sets the execution context, default is os/exec
SetExecutor(exec.Executor)
// Name of executable (to check if installed and for debug)
Name() string
// Fetch updates the package cache/databse

View File

@ -1,10 +1,12 @@
package pkg
import (
"os/exec"
)
import "git.xdrm.io/go/nix-amer/internal/exec"
type dnf struct{}
type dnf struct{ exec exec.Executor }
func (d *dnf) SetExecutor(_exec exec.Executor) {
d.exec = _exec
}
func (d dnf) Name() string { return "dnf" }
@ -13,17 +15,17 @@ func (d dnf) Fetch() error {
}
func (d dnf) Upgrade() error {
err := exec.Command(d.Name(), "upgrade").Run()
exec.Command(d.Name(), "autoremove").Run()
err := d.exec.Command(d.Name(), "upgrade").Run()
d.exec.Command(d.Name(), "autoremove").Run()
return err
}
func (d dnf) Install(_pkg string) error {
return exec.Command(d.Name(), "install", _pkg).Run()
return d.exec.Command(d.Name(), "install", _pkg).Run()
}
func (d dnf) Remove(_pkg string) error {
err := exec.Command(d.Name(), "remove", _pkg).Run()
exec.Command(d.Name(), "autoremove").Run()
err := d.exec.Command(d.Name(), "remove", _pkg).Run()
d.exec.Command(d.Name(), "autoremove").Run()
return err
}

View File

@ -1,10 +1,12 @@
package pkg
import (
"os/exec"
)
import "git.xdrm.io/go/nix-amer/internal/exec"
type eopkg struct{}
type eopkg struct{ exec exec.Executor }
func (d *eopkg) SetExecutor(_exec exec.Executor) {
d.exec = _exec
}
func (d eopkg) Name() string { return "eopkg" }
@ -13,18 +15,18 @@ func (d eopkg) Fetch() error {
}
func (d eopkg) Upgrade() error {
err := exec.Command(d.Name(), "upgrade").Run()
exec.Command(d.Name(), "remove-orphans").Run()
err := d.exec.Command(d.Name(), "upgrade").Run()
d.exec.Command(d.Name(), "remove-orphans").Run()
return err
}
func (d eopkg) Install(_pkg string) error {
err := exec.Command(d.Name(), "install", _pkg).Run()
err := d.exec.Command(d.Name(), "install", _pkg).Run()
return err
}
func (d eopkg) Remove(_pkg string) error {
err := exec.Command(d.Name(), "remove", _pkg).Run()
exec.Command(d.Name(), "remove-orphans").Run()
err := d.exec.Command(d.Name(), "remove", _pkg).Run()
d.exec.Command(d.Name(), "remove-orphans").Run()
return err
}

View File

@ -2,6 +2,7 @@ package pkg
import (
"errors"
"git.xdrm.io/go/nix-amer/internal/exec"
)
// ErrUnknownManager is raised when the asked manager does not exist
@ -13,7 +14,7 @@ var ErrUnknownManager = errors.New("unknown package manager")
var ErrNotInstalled = errors.New("no candidate installed")
// Load a specific package-manager by its name
func Load(_manager string) (PackageManager, error) {
func Load(_manager string, _exec exec.Executor) (PackageManager, error) {
// 1. create manager (fail if unknown)
var manager PackageManager
@ -39,6 +40,7 @@ func Load(_manager string) (PackageManager, error) {
// return nil, ErrNotInstalled
// }
manager.SetExecutor(_exec)
return manager, nil
}

View File

@ -1,12 +1,37 @@
package pkg
import (
"git.xdrm.io/go/nix-amer/internal/exec"
"testing"
)
/////////////////// MOCKUP START ///////////////////
type MockupCommand struct {
Out []byte
Err error
}
func (c MockupCommand) Run() error { return c.Err }
func (c MockupCommand) Output() ([]byte, error) { return c.Out, c.Err }
type MockupExecutor struct {
Out []byte
Err error
}
func (d MockupExecutor) Command(cmd string, args ...string) exec.Command {
return &MockupCommand{Out: d.Out, Err: d.Err}
}
/////////////////// MOCKUP END ///////////////////
func TestUnknownManager(t *testing.T) {
_, err := Load("apt-put")
execctx := new(MockupExecutor)
execctx.Err = nil
execctx.Out = []byte{}
_, err := Load("apt-put", execctx)
if err != ErrUnknownManager {
t.Errorf("expected <%s>, got <%s>", ErrUnknownManager, err)
t.Fail()
@ -14,8 +39,11 @@ func TestUnknownManager(t *testing.T) {
}
func TestKnownManager(t *testing.T) {
execctx := new(MockupExecutor)
execctx.Err = nil
execctx.Out = []byte{}
_, err := Load("apt-get")
_, err := Load("apt-get", execctx)
if err != nil {
t.Errorf("unexpected error <%s>", err)
t.Fail()

View File

@ -1,10 +1,12 @@
package pkg
import (
"os/exec"
)
import "git.xdrm.io/go/nix-amer/internal/exec"
type pacman struct{}
type pacman struct{ exec exec.Executor }
func (d *pacman) SetExecutor(_exec exec.Executor) {
d.exec = _exec
}
func (d pacman) Name() string { return "pacman" }
@ -13,18 +15,18 @@ func (d pacman) Fetch() error {
}
func (d pacman) Upgrade() error {
err := exec.Command(d.Name(), "-Syu").Run()
exec.Command(d.Name(), "-Ru").Run()
err := d.exec.Command(d.Name(), "-Syu").Run()
d.exec.Command(d.Name(), "-Ru").Run()
return err
}
func (d pacman) Install(_pkg string) error {
err := exec.Command(d.Name(), "-S", _pkg).Run()
err := d.exec.Command(d.Name(), "-S", _pkg).Run()
return err
}
func (d pacman) Remove(_pkg string) error {
err := exec.Command(d.Name(), "-R", _pkg).Run()
exec.Command(d.Name(), "-Ru").Run()
err := d.exec.Command(d.Name(), "-R", _pkg).Run()
d.exec.Command(d.Name(), "-Ru").Run()
return err
}

View File

@ -1,10 +1,12 @@
package pkg
import (
"os/exec"
)
import "git.xdrm.io/go/nix-amer/internal/exec"
type yum struct{}
type yum struct{ exec exec.Executor }
func (d *yum) SetExecutor(_exec exec.Executor) {
d.exec = _exec
}
func (d yum) Name() string { return "yum" }
@ -13,13 +15,13 @@ func (d yum) Fetch() error {
}
func (d yum) Upgrade() error {
return exec.Command(d.Name(), "update").Run()
return d.exec.Command(d.Name(), "update").Run()
}
func (d yum) Install(_pkg string) error {
return exec.Command(d.Name(), "install", _pkg).Run()
return d.exec.Command(d.Name(), "install", _pkg).Run()
}
func (d yum) Remove(_pkg string) error {
return exec.Command(d.Name(), "remove", _pkg).Run()
return d.exec.Command(d.Name(), "remove", _pkg).Run()
}

View File

@ -1,10 +1,16 @@
package ser
import (
"git.xdrm.io/go/nix-amer/internal/exec"
)
// DefaultManager if not empty is the default service-manager to use when missing
var DefaultManager = "systemd"
// ServiceManager is the common interface for service managers (systemd, init.d)
type ServiceManager interface {
// SetExecContext sets the execution context, default is os/exec
SetExecutor(exec.Executor)
// Name of executable (to check if installed and for debug)
Name() string
// Exec a specific action on a service

View File

@ -2,6 +2,7 @@ package ser
import (
"errors"
"git.xdrm.io/go/nix-amer/internal/exec"
)
// ErrUnknownManager is raised when the asked manager does not exist
@ -13,7 +14,7 @@ var ErrUnknownManager = errors.New("unknown service manager")
var ErrNotInstalled = errors.New("no candidate installed")
// Load a specific service-manager by its name
func Load(_manager string) (ServiceManager, error) {
func Load(_manager string, _exec exec.Executor) (ServiceManager, error) {
// 1. create manager (fail if unknown)
var manager ServiceManager
@ -29,6 +30,7 @@ func Load(_manager string) (ServiceManager, error) {
// return nil, ErrNotInstalled
// }
manager.SetExecutor(_exec)
return manager, nil
}

View File

@ -1,14 +1,18 @@
package ser
import (
"os/exec"
"git.xdrm.io/go/nix-amer/internal/exec"
)
type systemd struct{}
type systemd struct{ exec exec.Executor }
// available actions
var actions = []string{"enable", "disable", "start", "stop", "reload", "restart"}
func (d *systemd) SetExecutor(_exec exec.Executor) {
d.exec = _exec
}
func (d systemd) Name() string { return "systemctl" }
func (d systemd) Exec(action, service string) error {
@ -26,6 +30,6 @@ func (d systemd) Exec(action, service string) error {
}
// 2. execute command
return exec.Command("systemctl", action, service).Run()
return d.exec.Command("systemctl", action, service).Run()
}