create os/exec generic interface (internal/exec) with 'Default' wrapping os/exec + make tests do not use it
This commit is contained in:
parent
2901a4edd4
commit
1df8f9df9e
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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...)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue