adds option structs, ready for Show implementation

This commit is contained in:
Tai Groot 2021-05-15 13:49:34 -07:00
parent 7bedb452e4
commit 8a7c865b5f
Signed by: taigrr
GPG Key ID: D00C269A87614812
5 changed files with 145 additions and 78 deletions

View File

@ -46,9 +46,11 @@ import (
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
userMode := false
// Equivalent to `systemctl enable nginx` with a 10 second timeout
err := systemctl.Enable(ctx, "nginx", userMode)
opts := Options{
usermode: false,
}
err := Enable(ctx, unit, opts)
if err != nil {
log.Fatalf("unable to enable unit %s: %v", "nginx", err)
}

5
structs.go Normal file
View File

@ -0,0 +1,5 @@
package systemctl
type Options struct {
usermode bool
}

View File

@ -2,98 +2,143 @@ package systemctl
import (
"context"
"fmt"
"regexp"
)
// TODO
func IsFailed(ctx context.Context, unit string, usermode bool) (bool, error) {
func IsFailed(ctx context.Context, unit string, opts Options) (bool, error) {
var args = []string{"is-failed", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
stdout, _, _, err := execute(ctx, args)
if matched, _ := regexp.MatchString(`inactive`, stdout); matched {
return false, nil
}
// TODO
func IsActive(ctx context.Context, unit string, usermode bool) (bool, error) {
} else if matched, _ := regexp.MatchString(`active`, stdout); matched {
return false, nil
} else if matched, _ := regexp.MatchString(`failed`, stdout); matched {
return true, nil
}
return false, err
}
// TODO
func Status(ctx context.Context, unit string, usermode bool) (bool, error) {
func IsActive(ctx context.Context, unit string, opts Options) (bool, error) {
var args = []string{"is-active", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
stdout, _, _, err := execute(ctx, args)
if matched, _ := regexp.MatchString(`inactive`, stdout); matched {
return false, nil
} else if matched, _ := regexp.MatchString(`active`, stdout); matched {
return true, nil
} else if matched, _ := regexp.MatchString(`failed`, stdout); matched {
return false, nil
}
return false, err
}
// TODO
func Restart(ctx context.Context, unit string, usermode bool) error {
return nil
func IsEnabled(ctx context.Context, unit string, opts Options) (bool, error) {
var args = []string{"is-enabled", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
stdout, _, _, err := execute(ctx, args)
if matched, _ := regexp.MatchString(`enabled`, stdout); matched {
return true, nil
} else if matched, _ := regexp.MatchString(`disabled`, stdout); matched {
return false, nil
}
return false, err
}
// TODO
func Start(ctx context.Context, unit string, usermode bool) error {
return nil
func Status(ctx context.Context, unit string, opts Options) (string, error) {
var args = []string{"status", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
stdout, _, _, err := execute(ctx, args)
return stdout, err
}
// TODO
func Stop(ctx context.Context, unit string, usermode bool) error {
return nil
func Restart(ctx context.Context, unit string, opts Options) error {
var args = []string{"restart", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
_, _, _, err := execute(ctx, args)
return err
}
func Enable(ctx context.Context, unit string, usermode bool) error {
func Start(ctx context.Context, unit string, opts Options) error {
var args = []string{"start", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
_, _, _, err := execute(ctx, args)
return err
}
func Stop(ctx context.Context, unit string, opts Options) error {
var args = []string{"stop", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
_, _, _, err := execute(ctx, args)
return err
}
func Enable(ctx context.Context, unit string, opts Options) error {
var args = []string{"enable", "--system", unit}
if usermode {
if opts.usermode {
args[1] = "--user"
}
_, stderr, code, err := execute(ctx, args)
customErr := filterErr(stderr)
if customErr != nil {
return customErr
}
if err != nil {
_, _, _, err := execute(ctx, args)
return err
}
if code != 0 {
return fmt.Errorf("received error code %d for stderr `%s`: %w", code, stderr, ErrUnspecified)
}
return nil
}
func Disable(ctx context.Context, unit string, usermode bool) error {
func Disable(ctx context.Context, unit string, opts Options) error {
var args = []string{"disable", "--system", unit}
if usermode {
if opts.usermode {
args[1] = "--user"
}
_, stderr, code, err := execute(ctx, args)
customErr := filterErr(stderr)
if customErr != nil {
return customErr
}
if err != nil {
_, _, _, err := execute(ctx, args)
return err
}
if code != 0 {
return fmt.Errorf("received error code %d for stderr `%s`: %w", code, stderr, ErrUnspecified)
}
return nil
}
// TODO
func IsEnabled(ctx context.Context, unit string, usermode bool) (bool, error) {
return false, nil
}
// TODO
func DaemonReload(ctx context.Context, unit string, usermode bool) error {
return nil
func DaemonReload(ctx context.Context, opts Options) error {
var args = []string{"daemon-reload", "--system"}
if opts.usermode {
args[1] = "--user"
}
_, _, _, err := execute(ctx, args)
return err
}
//TODO
func Show(ctx context.Context, unit string, property string, usermode bool) (string, error) {
return "", nil
func Show(ctx context.Context, unit string, property string, opts Options) (string, error) {
var args = []string{"show", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
_, _, _, err := execute(ctx, args)
return "", err
}
//TODO
func Mask(ctx context.Context, unit string, usermode bool) error {
return nil
func Mask(ctx context.Context, unit string, opts Options) error {
var args = []string{"mask", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
_, _, _, err := execute(ctx, args)
return err
}
func Unmask(ctx context.Context, unit string, usermode bool) error {
return nil
func Unmask(ctx context.Context, unit string, opts Options) error {
var args = []string{"unmask", "--system", unit}
if opts.usermode {
args[1] = "--user"
}
_, _, _, err := execute(ctx, args)
return err
}

View File

@ -10,7 +10,10 @@ func TestEnableNonexistant(t *testing.T) {
unit := "nonexistant"
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err := Enable(ctx, unit, true)
opts := Options{
usermode: true,
}
err := Enable(ctx, unit, opts)
if err != ErrDoesNotExist {
t.Errorf("error is %v, but should have been %v", err, ErrDoesNotExist)
}
@ -23,7 +26,10 @@ func TestEnableNoPermissions(t *testing.T) {
unit := "nginx"
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err := Enable(ctx, unit, false)
opts := Options{
usermode: false,
}
err := Enable(ctx, unit, opts)
if err != ErrInsufficientPermissions {
t.Errorf("error is %v, but should have been %v", err, ErrInsufficientPermissions)
}
@ -37,7 +43,10 @@ func TestEnableSuccess(t *testing.T) {
unit := "syncthing"
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err := Enable(ctx, unit, true)
opts := Options{
usermode: true,
}
err := Enable(ctx, unit, opts)
if err != nil {
t.Errorf("error is %v, but should have been %v", err, nil)
}

26
util.go
View File

@ -3,6 +3,7 @@ package systemctl
import (
"bytes"
"context"
"fmt"
"os/exec"
"regexp"
)
@ -37,27 +38,32 @@ func execute(ctx context.Context, args []string) (string, string, int, error) {
warnings = stderr.String()
code = cmd.ProcessState.ExitCode()
customErr := filterErr(warnings)
if customErr != nil {
err = customErr
}
if code != 0 && err == nil {
err = fmt.Errorf("received error code %d for stderr `%s`: %w", code, warnings, ErrUnspecified)
}
return output, warnings, code, err
}
func filterErr(stderr string) error {
matched, _ := regexp.MatchString(`does not exist`, stderr)
if matched {
if matched, _ := regexp.MatchString(`does not exist`, stderr); matched {
return ErrDoesNotExist
}
matched, _ = regexp.MatchString(`Interactive authentication required`, stderr)
if matched {
if matched, _ := regexp.MatchString(`No such file or directory`, stderr); matched {
return ErrDoesNotExist
}
if matched, _ := regexp.MatchString(`Interactive authentication required`, stderr); matched {
return ErrInsufficientPermissions
}
matched, _ = regexp.MatchString(`Access denied`, stderr)
if matched {
if matched, _ := regexp.MatchString(`Access denied`, stderr); matched {
return ErrInsufficientPermissions
}
matched, _ = regexp.MatchString(`Failed`, stderr)
if matched {
if matched, _ := regexp.MatchString(`Failed`, stderr); matched {
return ErrUnspecified
}
return nil
}