add DryRun() method for instruction common interface | add DryRun() method to all instructions | TODO: tests + install/delete
This commit is contained in:
parent
2f95acb851
commit
1a7e1c2db0
|
@ -112,7 +112,13 @@ func NewReader(ctx *instruction.ExecutionContext, buildfile io.Reader) (*Reader,
|
|||
}
|
||||
|
||||
// Execute the current buildfile instruction by instruction
|
||||
func (r *Reader) Execute() error {
|
||||
// if <dryRun> is set to TRUE, run on dry-run mode
|
||||
func (r *Reader) Execute(_dryRun ...bool) error {
|
||||
|
||||
dryRun := true
|
||||
if len(_dryRun) < 1 || !_dryRun[0] {
|
||||
dryRun = false
|
||||
}
|
||||
|
||||
// 1. update package list
|
||||
// err := r.Context.PackageManager.Fetch()
|
||||
|
@ -168,7 +174,7 @@ func (r *Reader) Execute() error {
|
|||
|
||||
// 3. launch [pre] (it set)
|
||||
if pre != nil {
|
||||
execSection(pre, *r.Context, preTable, refresh, wg)
|
||||
execSection(pre, *r.Context, preTable, dryRun, refresh, wg)
|
||||
time.Sleep(time.Second * 2)
|
||||
}
|
||||
|
||||
|
@ -182,7 +188,7 @@ func (r *Reader) Execute() error {
|
|||
if !ok {
|
||||
continue
|
||||
}
|
||||
go execSection(sec, *r.Context, &table[i], refresh, wg)
|
||||
go execSection(sec, *r.Context, &table[i], dryRun, refresh, wg)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
@ -192,11 +198,17 @@ func (r *Reader) Execute() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func execSection(section *[]instruction.T, ctx instruction.ExecutionContext, tsec *tableSection, refresher chan<- bool, wg *sync.WaitGroup) {
|
||||
func execSection(section *[]instruction.T, ctx instruction.ExecutionContext, tsec *tableSection, dryRun bool, refresher chan<- bool, wg *sync.WaitGroup) {
|
||||
|
||||
for i, inst := range *section {
|
||||
tsec.instructions[i].start = time.Now()
|
||||
_, err := inst.Exec(ctx)
|
||||
var err error = nil
|
||||
if dryRun {
|
||||
_, err = inst.DryRun(ctx)
|
||||
} else {
|
||||
_, err = inst.Exec(ctx)
|
||||
|
||||
}
|
||||
tsec.instructions[i].stop = time.Now()
|
||||
tsec.instructions[i].stopped = true
|
||||
tsec.instructions[i].err = err
|
||||
|
|
|
@ -39,3 +39,7 @@ func (d alias) Exec(ctx ExecutionContext) ([]byte, error) {
|
|||
ctx.Alias[d.Name] = d.Value
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d alias) DryRun(ctx ExecutionContext) ([]byte, error) {
|
||||
return d.Exec(ctx)
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ type T interface {
|
|||
Build(string) error
|
||||
// Exec the given instruction
|
||||
Exec(ExecutionContext) ([]byte, error)
|
||||
// DryRun checks the success of the given instruction without actually running it (non-destructive)
|
||||
DryRun(ExecutionContext) ([]byte, error)
|
||||
}
|
||||
|
||||
// ExecutionContext contains system-specific drivers to manage the host
|
||||
|
|
|
@ -45,3 +45,38 @@ func (d copy) Exec(ctx ExecutionContext) ([]byte, error) {
|
|||
return nil, nil
|
||||
|
||||
}
|
||||
|
||||
func (d copy) DryRun(ctx ExecutionContext) ([]byte, error) {
|
||||
|
||||
// 1. fail if source file not found
|
||||
if _, err := os.Stat(d.Src); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("cannot find file '%s'", d.Src)
|
||||
}
|
||||
|
||||
// 2. if destination to create : try to create (then remove)
|
||||
if _, err := os.Stat(d.Src); os.IsNotExist(err) {
|
||||
|
||||
file, err := os.OpenFile(d.Dst, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot copy '%s' to '%s' | %s", d.Src, d.Dst, err)
|
||||
}
|
||||
file.Close()
|
||||
|
||||
if err := os.Remove(d.Dst); err != nil {
|
||||
return nil, fmt.Errorf("cannot tmp file at '%s' | %s", d.Dst, err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
||||
// 3. if destination exists : check write permission
|
||||
file, err := os.OpenFile(d.Dst, os.O_APPEND|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot copy '%s' to '%s' | %s", d.Src, d.Dst, err)
|
||||
}
|
||||
file.Close()
|
||||
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
|
|
@ -33,3 +33,7 @@ func (d delete) Exec(ctx ExecutionContext) ([]byte, error) {
|
|||
return nil, nil
|
||||
|
||||
}
|
||||
|
||||
func (d delete) DryRun(ctx ExecutionContext) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -33,3 +33,7 @@ func (d install) Exec(ctx ExecutionContext) ([]byte, error) {
|
|||
return nil, nil
|
||||
|
||||
}
|
||||
|
||||
func (d install) DryRun(ctx ExecutionContext) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -40,3 +40,21 @@ func (d run) Exec(ctx ExecutionContext) ([]byte, error) {
|
|||
return nil, nil
|
||||
|
||||
}
|
||||
func (d run) DryRun(ctx ExecutionContext) ([]byte, error) {
|
||||
|
||||
// 1. get file / alias
|
||||
path := d.raw
|
||||
if !strings.Contains(path, "/") {
|
||||
if p, exists := ctx.Alias[path]; exists {
|
||||
path = p
|
||||
}
|
||||
}
|
||||
|
||||
// 1. fail if file not found
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("cannot find script '%s'", path)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
|
|
@ -60,3 +60,17 @@ func (d service) Exec(ctx ExecutionContext) ([]byte, error) {
|
|||
return nil, nil
|
||||
|
||||
}
|
||||
func (d service) DryRun(ctx ExecutionContext) ([]byte, error) {
|
||||
|
||||
// fail if a service does not exist
|
||||
for _, service := range d.Services {
|
||||
|
||||
if err := ctx.ServiceManager.Exec("status", service); err != nil {
|
||||
return nil, fmt.Errorf("cannot find service '%s' | %s", service, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/xdrm-brackets/nix-amer/internal/cnf"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -94,3 +95,57 @@ func (d set) Exec(ctx ExecutionContext) ([]byte, error) {
|
|||
return nil, nil
|
||||
|
||||
}
|
||||
func (d set) DryRun(ctx ExecutionContext) ([]byte, error) {
|
||||
|
||||
// 1. get file / alias
|
||||
path := d.File
|
||||
if !strings.Contains(path, "/") {
|
||||
if p, exists := ctx.Alias[path]; exists {
|
||||
path = p
|
||||
}
|
||||
}
|
||||
|
||||
// 2. fail if file not found
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("cannot find file '%s'", path)
|
||||
}
|
||||
|
||||
// 3. try to load format
|
||||
format, err := cnf.Load(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 4. try to update value
|
||||
if !format.Set(d.Path, d.Value) {
|
||||
return nil, ErrCannotSet
|
||||
}
|
||||
|
||||
// 5. fail on missing write permission
|
||||
file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, os.FileMode(0775))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot update '%s' | %s", path, err)
|
||||
}
|
||||
file.Close()
|
||||
|
||||
// 6. create non-destructive dry-run folder
|
||||
dryRunFolder := "/tmp/dry-run"
|
||||
if err := os.MkdirAll(dryRunFolder, os.FileMode(0777)); err != nil {
|
||||
return nil, fmt.Errorf("cannot create dry-run folder | %s", err)
|
||||
|
||||
}
|
||||
|
||||
// 7. create updated file inside .dry-run
|
||||
tmpout := filepath.Join(dryRunFolder, strings.Replace(path, "/", "-", -1))
|
||||
file, err = os.Create(tmpout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create dry-run file '%s' | %s", tmpout, err)
|
||||
}
|
||||
defer file.Close()
|
||||
if _, err = format.WriteTo(file); err != nil {
|
||||
return nil, fmt.Errorf("cannot write dry-run file '%s' | %s", tmpout, err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
type systemd struct{ exec exec.Executor }
|
||||
|
||||
// available actions
|
||||
var actions = []string{"enable", "disable", "start", "stop", "reload", "restart"}
|
||||
var actions = []string{"enable", "disable", "status", "start", "stop", "reload", "restart"}
|
||||
|
||||
func (d *systemd) SetExecutor(_exec exec.Executor) {
|
||||
d.exec = _exec
|
||||
|
|
9
main.go
9
main.go
|
@ -43,13 +43,10 @@ func main() {
|
|||
fmt.Printf("%s\n", clifmt.Color(32, "valid"))
|
||||
|
||||
// stop here if dry run
|
||||
if dryRun {
|
||||
return
|
||||
}
|
||||
|
||||
// 3. Execute
|
||||
fmt.Printf("------\n")
|
||||
err = instructions.Execute()
|
||||
err = instructions.Execute(dryRun)
|
||||
if err != nil {
|
||||
fmt.Printf("%s\n", clifmt.Warn(err.Error()))
|
||||
return
|
||||
|
@ -58,4 +55,8 @@ func main() {
|
|||
clifmt.Align("finished in")
|
||||
fmt.Printf("%ss\n", clifmt.Color(32, fmt.Sprintf("%.2f", time.Now().Sub(start).Seconds())))
|
||||
|
||||
if dryRun {
|
||||
fmt.Printf("\n%s %s\n", clifmt.Info("updated configurations are inside"), clifmt.Color(32, "/tmp/dry-run"))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue