util: Port all multierr code to new errwrap package

This cleans things up and simplifies a lot of the code. Also it's easier
to just import one error package when needed.
This commit is contained in:
James Shubin
2019-03-12 16:51:37 -04:00
parent 880652f5d4
commit 753d1104ef
21 changed files with 83 additions and 146 deletions

View File

@@ -25,8 +25,7 @@ import (
"time"
"github.com/purpleidea/mgmt/util"
multierr "github.com/hashicorp/go-multierror"
"github.com/purpleidea/mgmt/util/errwrap"
)
// New builds a new converger coordinator.
@@ -323,9 +322,8 @@ func (obj *Coordinator) runStateFns(converged bool) error {
for _, name := range keys { // run in deterministic order
fn := obj.stateFns[name]
// call an arbitrary function
if e := fn(converged); e != nil {
err = multierr.Append(err, e) // list of errors
}
e := fn(converged)
err = errwrap.Append(err, e) // list of errors
}
return err
}

View File

@@ -27,7 +27,6 @@ import (
"github.com/purpleidea/mgmt/pgraph"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
"golang.org/x/time/rate"
)
@@ -378,7 +377,7 @@ Loop:
if err != nil {
failed = true
close(obj.state[vertex].watchDone) // causes doneChan to close
reterr = multierr.Append(reterr, err) // permanent failure
reterr = errwrap.Append(reterr, err) // permanent failure
continue
}
if obj.Debug {
@@ -459,7 +458,7 @@ Loop:
if e != nil {
failed = true
close(obj.state[vertex].limitDone) // causes doneChan to close
reterr = multierr.Append(reterr, e) // permanent failure
reterr = errwrap.Append(reterr, e) // permanent failure
break LimitWait
}
if obj.Debug {
@@ -499,7 +498,7 @@ Loop:
if e != nil {
failed = true
close(obj.state[vertex].limitDone) // causes doneChan to close
reterr = multierr.Append(reterr, e) // permanent failure
reterr = errwrap.Append(reterr, e) // permanent failure
break RetryWait
}
if obj.Debug {
@@ -547,7 +546,7 @@ Loop:
// to exit right here... (It happens when we loop...)
failed = true
close(obj.state[vertex].processDone) // causes doneChan to close
reterr = multierr.Append(reterr, err) // permanent failure
reterr = errwrap.Append(reterr, err) // permanent failure
continue
} // retry loop

View File

@@ -23,8 +23,6 @@ import (
"github.com/purpleidea/mgmt/engine"
"github.com/purpleidea/mgmt/pgraph"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
)
// AutoEdge adds the automatic edges to the graph.
@@ -49,7 +47,7 @@ func AutoEdge(graph *pgraph.Graph, debug bool, logf func(format string, v ...int
for _, res := range sorted { // for each vertexes autoedges
autoEdgeObj, e := res.AutoEdges()
if e != nil {
err = multierr.Append(err, e) // collect all errors
err = errwrap.Append(err, e) // collect all errors
continue
}
if autoEdgeObj == nil {

View File

@@ -28,8 +28,6 @@ import (
"github.com/purpleidea/mgmt/pgraph"
"github.com/purpleidea/mgmt/util/errwrap"
"github.com/purpleidea/mgmt/util/semaphore"
multierr "github.com/hashicorp/go-multierror"
)
// Engine encapsulates a generic graph and manages its operations.
@@ -380,20 +378,16 @@ func (obj *Engine) Pause(fastPause bool) error {
// Close triggers a shutdown. Engine must be already paused before this is run.
func (obj *Engine) Close() error {
var reterr error
emptyGraph, err := pgraph.NewGraph("empty")
if err != nil {
reterr = multierr.Append(reterr, err) // list of errors
}
emptyGraph, reterr := pgraph.NewGraph("empty")
// this is a graph switch (graph sync) that switches to an empty graph!
if err := obj.Load(emptyGraph); err != nil { // copy in empty graph
reterr = multierr.Append(reterr, err)
reterr = errwrap.Append(reterr, err)
}
// FIXME: Do we want to run commit if Load failed? Does this even work?
// the commit will cause the graph sync to shut things down cleverly...
if err := obj.Commit(); err != nil {
reterr = multierr.Append(reterr, err)
reterr = errwrap.Append(reterr, err)
}
obj.wg.Wait() // for now, this doesn't need to be a separate Wait() method

View File

@@ -23,13 +23,13 @@ import (
"fmt"
"testing"
multierr "github.com/hashicorp/go-multierror"
"github.com/purpleidea/mgmt/util/errwrap"
)
func TestMultiErr(t *testing.T) {
var err error
e := fmt.Errorf("some error")
err = multierr.Append(err, e) // build an error from a nil base
err = errwrap.Append(err, e) // build an error from a nil base
// ensure that this lib allows us to append to a nil
if err == nil {
t.Errorf("missing error")

View File

@@ -23,9 +23,8 @@ import (
"strconv"
"strings"
"github.com/purpleidea/mgmt/util/errwrap"
"github.com/purpleidea/mgmt/util/semaphore"
multierr "github.com/hashicorp/go-multierror"
)
// SemaSep is the trailing separator to split the semaphore id from the size.
@@ -46,9 +45,8 @@ func (obj *Engine) semaLock(semas []string) error {
}
obj.slock.Unlock()
if err := sema.P(1); err != nil { // lock!
reterr = multierr.Append(reterr, err) // list of errors
}
err := sema.P(1) // lock!
reterr = errwrap.Append(reterr, err) // list of errors
}
return reterr
}
@@ -65,9 +63,8 @@ func (obj *Engine) semaUnlock(semas []string) error {
panic(fmt.Sprintf("graph: sema: %s does not exist", id))
}
if err := sema.V(1); err != nil { // unlock!
reterr = multierr.Append(reterr, err) // list of errors
}
err := sema.V(1) // unlock!
reterr = errwrap.Append(reterr, err) // list of errors
}
return reterr
}

View File

@@ -24,8 +24,6 @@ import (
"github.com/purpleidea/mgmt/engine"
engineUtil "github.com/purpleidea/mgmt/engine/util"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
)
// SendRecv pulls in the sent values into the receive slots. It is called by the
@@ -50,25 +48,25 @@ func (obj *Engine) SendRecv(res engine.RecvableRes) (map[string]bool, error) {
if st == nil {
e := fmt.Errorf("received nil value from: %s", v.Res)
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
if e := engineUtil.StructFieldCompat(st, v.Key, res, k); e != nil {
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
// send
m1, e := engineUtil.StructTagToFieldName(st)
if e != nil {
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
key1, exists := m1[v.Key]
if !exists {
e := fmt.Errorf("requested key of `%s` not found in send struct", v.Key)
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
@@ -80,13 +78,13 @@ func (obj *Engine) SendRecv(res engine.RecvableRes) (map[string]bool, error) {
// recv
m2, e := engineUtil.StructTagToFieldName(res)
if e != nil {
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
key2, exists := m2[k]
if !exists {
e := fmt.Errorf("requested key of `%s` not found in recv struct", k)
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
@@ -103,7 +101,7 @@ func (obj *Engine) SendRecv(res engine.RecvableRes) (map[string]bool, error) {
// i think we probably want the same kind, at least for now...
if kind1 != kind2 {
e := fmt.Errorf("kind mismatch between %s: %s and %s: %s", v.Res, kind1, res, kind2)
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
@@ -111,21 +109,21 @@ func (obj *Engine) SendRecv(res engine.RecvableRes) (map[string]bool, error) {
// FIXME: do we want to relax this for string -> *string ?
if e := TypeCmp(value1, value2); e != nil {
e := errwrap.Wrapf(e, "type mismatch between %s and %s", v.Res, res)
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
// if we can't set, then well this is pointless!
if !value2.CanSet() {
e := fmt.Errorf("can't set %s.%s", res, k)
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}
// if we can't interface, we can't compare...
if !value1.CanInterface() || !value2.CanInterface() {
e := fmt.Errorf("can't interface %s.%s", res, k)
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
continue
}

View File

@@ -43,7 +43,6 @@ import (
cwe "github.com/aws/aws-sdk-go/service/cloudwatchevents"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/sns"
multierr "github.com/hashicorp/go-multierror"
)
func init() {
@@ -393,17 +392,14 @@ func (obj *AwsEc2Res) Close() error {
// clean up sns objects created by Init/snsWatch
if obj.snsClient != nil {
// delete the topic and associated subscriptions
if err := obj.snsDeleteTopic(obj.snsTopicArn); err != nil {
errList = multierr.Append(errList, err)
}
e1 := obj.snsDeleteTopic(obj.snsTopicArn)
errList = errwrap.Append(errList, e1)
// remove the target
if err := obj.cweRemoveTarget(CweTargetID, CweRuleName); err != nil {
errList = multierr.Append(errList, err)
}
e2 := obj.cweRemoveTarget(CweTargetID, CweRuleName)
errList = errwrap.Append(errList, e2)
// delete the cloudwatch rule
if err := obj.cweDeleteRule(CweRuleName); err != nil {
errList = multierr.Append(errList, err)
}
e3 := obj.cweDeleteRule(CweRuleName)
errList = errwrap.Append(errList, e3)
}
return errList

View File

@@ -33,8 +33,6 @@ import (
"github.com/purpleidea/mgmt/engine/traits"
engineUtil "github.com/purpleidea/mgmt/engine/util"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
)
func init() {
@@ -722,13 +720,7 @@ func (obj *ExecRes) cmdOutputRunner(ctx context.Context, cmd *exec.Cmd) (chan *c
// on EOF, scanner.Err() will be nil
reterr := scanner.Err()
if err := cmd.Wait(); err != nil { // always run Wait()
if reterr != nil {
reterr = multierr.Append(reterr, err)
} else {
reterr = err
}
}
reterr = errwrap.Append(reterr, cmd.Wait()) // always run Wait()
// send any misc errors we encounter on the channel
if reterr != nil {
select {

View File

@@ -37,7 +37,6 @@ import (
"github.com/purpleidea/mgmt/util/errwrap"
"github.com/purpleidea/mgmt/util/socketset"
multierr "github.com/hashicorp/go-multierror"
// XXX: Do NOT use subscribe methods from this lib, as they are racey and
// do not clean up spawned goroutines. Should be replaced when a suitable
// alternative is available.
@@ -179,9 +178,7 @@ func (obj *NetRes) Close() error {
return fmt.Errorf("socket file should not be the root path")
}
if obj.socketFile != "" { // safety
if err := os.Remove(obj.socketFile); err != nil {
errList = multierr.Append(errList, err)
}
errList = errwrap.Append(errList, os.Remove(obj.socketFile))
}
return errList

View File

@@ -30,7 +30,6 @@ import (
"github.com/purpleidea/mgmt/util/errwrap"
"github.com/godbus/dbus"
multierr "github.com/hashicorp/go-multierror"
)
// global tweaks of verbosity and code path
@@ -198,9 +197,8 @@ func (obj *Conn) matchSignal(ch chan *dbus.Signal, path dbus.ObjectPath, iface s
removeSignals := func() error {
var errList error
for i := len(argsList) - 1; i >= 0; i-- { // last in first out
if call := bus.Call(engineUtil.DBusRemoveMatch, 0, argsList[i]); call.Err != nil {
errList = multierr.Append(errList, call.Err)
}
call := bus.Call(engineUtil.DBusRemoveMatch, 0, argsList[i])
errList = errwrap.Append(errList, call.Err)
}
return errList
}

View File

@@ -26,8 +26,6 @@ import (
"time"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
)
// Cluster represents an mgmt cluster. It uses the instance building blocks to
@@ -83,9 +81,7 @@ func (obj *Cluster) Init() error {
dir: instancePrefix,
}
if e := obj.instances[h].Init(); e != nil {
err = multierr.Append(err, e)
}
err = errwrap.Append(err, obj.instances[h].Init())
}
return err
@@ -101,9 +97,7 @@ func (obj *Cluster) Close() error {
if !exists {
continue
}
if e := instance.Close(); e != nil {
err = multierr.Append(err, e)
}
err = errwrap.Append(err, instance.Close())
}
if !obj.Preserve {
if obj.dir == "" || obj.dir == "/" {
@@ -157,9 +151,7 @@ func (obj *Cluster) Kill() error {
if !exists {
continue
}
if e := instance.Kill(); e != nil {
err = multierr.Append(err, e)
}
err = errwrap.Append(err, instance.Kill())
}
return err
}
@@ -178,9 +170,7 @@ func (obj *Cluster) Quit(ctx context.Context) error {
if !exists {
continue
}
if e := instance.Quit(ctx); e != nil {
err = multierr.Append(err, e)
}
err = errwrap.Append(err, instance.Quit(ctx))
}
return err
}
@@ -198,9 +188,7 @@ func (obj *Cluster) Wait(ctx context.Context) error {
// TODO: do we want individual waits?
//ctx, cancel := context.WithTimeout(context.Background(), longTimeout*time.Second)
//defer cancel()
if e := instance.Wait(ctx); e != nil {
err = multierr.Append(err, e)
}
err = errwrap.Append(err, instance.Wait(ctx))
}
return err
}

View File

@@ -27,8 +27,6 @@ import (
"github.com/purpleidea/mgmt/lang/types"
"github.com/purpleidea/mgmt/pgraph"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
)
// State represents the state of a function vertex. This corresponds to an AST
@@ -167,9 +165,8 @@ func (obj *Engine) Init() error {
obj.state[vertex] = &State{Expr: expr} // store some state!
if e := obj.state[vertex].Init(); e != nil {
err = multierr.Append(err, e) // list of errors
}
e := obj.state[vertex].Init()
err = errwrap.Append(err, e) // list of errors
}
if err != nil { // usually due to `not found` errors
return errwrap.Wrapf(err, "could not load requested funcs")
@@ -201,14 +198,14 @@ func (obj *Engine) Validate() error {
// duplicate pointers would get closed twice, causing a panic...
if inList(node.handle, ptrs) { // check for duplicate ptrs!
e := fmt.Errorf("vertex `%s` has duplicate ptr", vertex)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
ptrs = append(ptrs, node.handle)
}
for _, edge := range obj.Graph.Edges() {
if _, ok := edge.(*Edge); !ok {
e := fmt.Errorf("edge `%s` was not the correct type", edge)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
}
if err != nil {
@@ -220,7 +217,7 @@ func (obj *Engine) Validate() error {
node := obj.state[vertex]
if exp := len(node.handle.Info().Sig.Ord); exp != count {
e := fmt.Errorf("expected %d inputs to `%s`, got %d", exp, node, count)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
}
@@ -254,30 +251,30 @@ func (obj *Engine) Validate() error {
sig := node2.handle.Info().Sig
if len(sig.Ord) == 0 {
e := fmt.Errorf("no input expected from `%s` to `%s` with arg `%s`", node1, node2, arg)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
continue
}
if count, exists := expected[node2][arg]; !exists {
e := fmt.Errorf("wrong input name from `%s` to `%s` with arg `%s`", node1, node2, arg)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
} else if count == 0 {
e := fmt.Errorf("duplicate input from `%s` to `%s` with arg `%s`", node1, node2, arg)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
expected[node2][arg]-- // subtract one use
out := node1.handle.Info().Sig.Out
if out == nil {
e := fmt.Errorf("no output possible from `%s` to `%s` with arg `%s`", node1, node2, arg)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
continue
}
typ, exists := sig.Map[arg] // key in struct
if !exists {
// second check of this!
e := fmt.Errorf("wrong input name from `%s` to `%s` with arg `%s`", node1, node2, arg)
err = multierr.Append(err, errwrap.Wrapf(e, "programming error"))
err = errwrap.Append(err, errwrap.Wrapf(e, "programming error"))
continue
}
@@ -287,7 +284,7 @@ func (obj *Engine) Validate() error {
// pass (output arg variants)
} else if typ.Cmp(out) != nil {
e := fmt.Errorf("type mismatch from `%s` (%s) to `%s` (%s) with arg `%s`", node1, out, node2, typ, arg)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
}
}
@@ -299,7 +296,7 @@ func (obj *Engine) Validate() error {
for arg, count := range m {
if count != 0 { // count should be zero if all were used
e := fmt.Errorf("missing input to `%s` on arg `%s`", node, arg)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
}
}
@@ -640,7 +637,7 @@ func (obj *Engine) Close() error {
if node.init { // did we Init this func?
if e := node.handle.Close(); e != nil {
e := errwrap.Wrapf(e, "problem closing func `%s`", node)
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
}
}
}

View File

@@ -27,8 +27,6 @@ import (
"github.com/purpleidea/mgmt/lang/types"
"github.com/purpleidea/mgmt/util"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
)
const (
@@ -276,18 +274,12 @@ Loop:
break Loop
}
e := errwrap.Wrapf(err, "problem streaming func")
if reterr != nil {
reterr = multierr.Append(reterr, e)
} else {
reterr = e
}
reterr = errwrap.Append(reterr, e)
}
}
if err := handle.Close(); err != nil {
if reterr != nil {
err = multierr.Append(err, reterr)
}
err = errwrap.Append(err, reterr)
return nil, errwrap.Wrapf(err, "problem closing func")
}

View File

@@ -31,7 +31,6 @@ import (
"github.com/purpleidea/mgmt/util"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
"github.com/spf13/afero"
"github.com/urfave/cli"
)
@@ -502,7 +501,7 @@ func (obj *GAPI) Next() chan gapi.Next {
// because we should tell the lang obj
// to shut down all the running facts.
if e := obj.LangClose(); e != nil {
err = multierr.Append(err, e) // list of errors
err = errwrap.Append(err, e) // list of errors
}
} else {

View File

@@ -24,8 +24,7 @@ import (
"github.com/purpleidea/mgmt/engine"
"github.com/purpleidea/mgmt/lang/types"
"github.com/purpleidea/mgmt/pgraph"
multierr "github.com/hashicorp/go-multierror"
"github.com/purpleidea/mgmt/util/errwrap"
)
// Node represents either a Stmt or an Expr. It contains the minimum set of
@@ -223,21 +222,21 @@ func (obj *Scope) Merge(scope *Scope) error {
for _, name := range namedVariables {
if _, exists := obj.Variables[name]; exists {
e := fmt.Errorf("variable `%s` was overwritten", name)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
obj.Variables[name] = scope.Variables[name]
}
for _, name := range namedFunctions {
if _, exists := obj.Functions[name]; exists {
e := fmt.Errorf("function `%s` was overwritten", name)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
obj.Functions[name] = scope.Functions[name]
}
for _, name := range namedClasses {
if _, exists := obj.Classes[name]; exists {
e := fmt.Errorf("class `%s` was overwritten", name)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
}
obj.Classes[name] = scope.Classes[name]
}

View File

@@ -31,7 +31,6 @@ import (
"github.com/purpleidea/mgmt/util"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
"github.com/spf13/afero"
)
@@ -142,9 +141,8 @@ func runInterpret(t *testing.T, code string) (*pgraph.Graph, error) {
graph, err := lang.Interpret()
if err != nil {
err := errwrap.Wrapf(err, "interpret failed")
if e := closeFn(); e != nil {
err = multierr.Append(err, e) // list of errors
}
e := closeFn()
err = errwrap.Append(err, e) // list of errors
return nil, err
}

View File

@@ -22,7 +22,7 @@ import (
"reflect"
"strings"
multierr "github.com/hashicorp/go-multierror"
"github.com/purpleidea/mgmt/util/errwrap"
)
// Basic types defined here as a convenience for use with Type.Cmp(X).
@@ -597,7 +597,7 @@ func (obj *Type) Cmp(typ *Type) error {
kerr := obj.Key.Cmp(typ.Key)
verr := obj.Val.Cmp(typ.Val)
if kerr != nil && verr != nil {
return multierr.Append(kerr, verr) // two errors
return errwrap.Append(kerr, verr) // two errors
}
if kerr != nil {
return kerr
@@ -964,7 +964,7 @@ func (obj *Type) ComplexCmp(typ *Type) (string, error) {
kstatus, kerr := obj.Key.ComplexCmp(typ.Key)
vstatus, verr := obj.Val.ComplexCmp(typ.Val)
if kerr != nil && verr != nil {
return "", multierr.Append(kerr, verr) // two errors
return "", errwrap.Append(kerr, verr) // two errors
}
if kerr != nil {
return "", kerr

View File

@@ -29,7 +29,6 @@ import (
"github.com/purpleidea/mgmt/puppet"
"github.com/purpleidea/mgmt/util/errwrap"
multierr "github.com/hashicorp/go-multierror"
"github.com/urfave/cli"
)
@@ -329,12 +328,11 @@ func (obj *GAPI) Close() error {
}
var err error
if e := obj.langGAPI.Close(); e != nil {
err = multierr.Append(err, errwrap.Wrapf(e, "closing lang GAPI failed"))
}
if e := obj.puppetGAPI.Close(); e != nil {
err = multierr.Append(err, errwrap.Wrapf(e, "closing Puppet GAPI failed"))
}
e1 := obj.langGAPI.Close()
err = errwrap.Append(err, errwrap.Wrapf(e1, "closing lang GAPI failed"))
e2 := obj.puppetGAPI.Close()
err = errwrap.Append(err, errwrap.Wrapf(e2, "closing Puppet GAPI failed"))
close(obj.closeChan)
obj.initialized = false // closed = true

View File

@@ -42,7 +42,6 @@ import (
"github.com/purpleidea/mgmt/util/errwrap"
etcdtypes "github.com/coreos/etcd/pkg/types"
multierr "github.com/hashicorp/go-multierror"
)
// Flags are some constant flags which are used throughout the program.
@@ -575,7 +574,7 @@ func (obj *Main) Run() error {
res, ok := v.(engine.Res)
if !ok {
e := fmt.Errorf("vertex `%s` is not a Res", v)
err = multierr.Append(err, e)
err = errwrap.Append(err, e)
continue // we'll catch the error later!
}
@@ -847,9 +846,8 @@ func (obj *Main) Close() error {
// run cleanup functions in reverse (defer) order
for i := len(obj.cleanup) - 1; i >= 0; i-- {
fn := obj.cleanup[i]
if e := fn(); e != nil {
err = multierr.Append(err, e) // list of errors
}
e := fn()
err = errwrap.Append(err, e) // list of errors
}
return err

View File

@@ -58,7 +58,8 @@ function consistent-imports() {
if grep $'\t"github.com/pkg/errors"' "$1"; then
return 1
fi
if grep $'\t"github.com/hashicorp/go-multierror"' "$1"; then # import as multierr
# import as github.com/purpleidea/mgmt/util/errwrap
if grep $'\t"github.com/hashicorp/go-multierror"' "$1"; then
return 1
fi
if grep $'\t"github.com/purpleidea/mgmt/engine/util"' "$1"; then # import as engineUtil