From ac8edce680bed84b63f814c31dfeb6b3add8fb63 Mon Sep 17 00:00:00 2001 From: Madhav Puri Date: Tue, 22 Mar 2016 21:59:19 -0700 Subject: [PATCH 1/4] use contiv/errored for errors Signed-off-by: Madhav Puri --- management/src/clusterctl/main.go | 4 ++-- management/src/clusterm/main.go | 5 +++-- management/src/clusterm/manager/client.go | 4 +++- management/src/clusterm/manager/events.go | 5 +++-- management/src/clusterm/manager/manager.go | 9 ++++----- management/src/clusterm/manager/utils.go | 9 ++++----- management/src/collins/client.go | 22 +++++++++++----------- management/src/configuration/ansible.go | 10 +++++----- management/src/inventory/asset.go | 6 +++--- management/src/inventory/asset_test.go | 10 +++++----- management/src/inventory/collins.go | 7 +++---- management/src/inventory/consts.go | 6 +++--- management/src/monitor/serf.go | 4 ++-- 13 files changed, 51 insertions(+), 50 deletions(-) diff --git a/management/src/clusterctl/main.go b/management/src/clusterctl/main.go index 3361591..de17053 100644 --- a/management/src/clusterctl/main.go +++ b/management/src/clusterctl/main.go @@ -3,16 +3,16 @@ package main import ( "bytes" "encoding/json" - "fmt" "os" log "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" "github.com/contiv/cluster/management/src/clusterm/manager" + "github.com/contiv/errored" ) var ( - errNodeNameMissing = func(c string) error { return fmt.Errorf("command %q expects a node name", c) } + errNodeNameMissing = func(c string) error { return errored.Errorf("command %q expects a node name", c) } clustermFlags = []cli.Flag{ cli.StringFlag{ diff --git a/management/src/clusterm/main.go b/management/src/clusterm/main.go index 10bfd19..713d19c 100644 --- a/management/src/clusterm/main.go +++ b/management/src/clusterm/main.go @@ -11,6 +11,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" "github.com/contiv/cluster/management/src/clusterm/manager" + "github.com/contiv/errored" "github.com/imdario/mergo" ) @@ -59,11 +60,11 @@ func main() { func mergeConfig(dst *manager.Config, srcJSON []byte) (*manager.Config, error) { src := &manager.Config{} if err := json.Unmarshal(srcJSON, src); err != nil { - return nil, fmt.Errorf("failed to parse configuration. Error: %s", err) + return nil, errored.Errorf("failed to parse configuration. Error: %s", err) } if err := mergo.MergeWithOverwrite(dst, src); err != nil { - return nil, fmt.Errorf("failed to merge configuration. Error: %s", err) + return nil, errored.Errorf("failed to merge configuration. Error: %s", err) } return dst, nil diff --git a/management/src/clusterm/manager/client.go b/management/src/clusterm/manager/client.go index 54e6648..11c8c4e 100644 --- a/management/src/clusterm/manager/client.go +++ b/management/src/clusterm/manager/client.go @@ -6,10 +6,12 @@ import ( "net/http" "net/url" "strings" + + "github.com/contiv/errored" ) var httpErrorResp = func(rsrc, status string, body []byte) error { - return fmt.Errorf("Request: %s Response status: %q. Response body: %s", rsrc, status, body) + return errored.Errorf("Request: %s Response status: %q. Response body: %s", rsrc, status, body) } // Client provides the methods for issuing post and get requests to cluster manager diff --git a/management/src/clusterm/manager/events.go b/management/src/clusterm/manager/events.go index 501b0a9..7f48d95 100644 --- a/management/src/clusterm/manager/events.go +++ b/management/src/clusterm/manager/events.go @@ -9,12 +9,13 @@ import ( log "github.com/Sirupsen/logrus" "github.com/contiv/cluster/management/src/configuration" "github.com/contiv/cluster/management/src/monitor" + "github.com/contiv/errored" ) // errInvalidJSON is the error returned when an invalid json value is specified for // the ansible extra variables configuration var errInvalidJSON = func(name string, err error) error { - return fmt.Errorf("%q should be a valid json. Error: %s", name, err) + return errored.Errorf("%q should be a valid json. Error: %s", name, err) } // event associates an event to corresponding processing logic @@ -192,7 +193,7 @@ func (e *nodeDecommissioned) process() error { } if isWorkerNode { - return fmt.Errorf("%q is a master node and it can only be decommissioned after all worker nodes have been decommissioned", e.nodeName) + return errored.Errorf("%q is a master node and it can only be decommissioned after all worker nodes have been decommissioned", e.nodeName) } } } diff --git a/management/src/clusterm/manager/manager.go b/management/src/clusterm/manager/manager.go index fa9a60d..384407a 100644 --- a/management/src/clusterm/manager/manager.go +++ b/management/src/clusterm/manager/manager.go @@ -13,12 +13,11 @@ package manager import ( - "fmt" - "github.com/contiv/cluster/management/src/collins" "github.com/contiv/cluster/management/src/configuration" "github.com/contiv/cluster/management/src/inventory" "github.com/contiv/cluster/management/src/monitor" + "github.com/contiv/errored" "github.com/mapuri/serf/client" ) @@ -83,7 +82,7 @@ type Manager struct { // if a failure occurs as part of initialization. func NewManager(config *Config) (*Manager, error) { if config == nil { - return nil, fmt.Errorf("nil config passed") + return nil, errored.Errorf("nil config passed") } var err error @@ -105,11 +104,11 @@ func NewManager(config *Config) (*Manager, error) { } if err := m.monitor.RegisterCb(monitor.Discovered, m.enqueueMonitorEvent); err != nil { - return nil, fmt.Errorf("failed to register node discovery callback. Error: %s", err) + return nil, errored.Errorf("failed to register node discovery callback. Error: %s", err) } if err := m.monitor.RegisterCb(monitor.Disappeared, m.enqueueMonitorEvent); err != nil { - return nil, fmt.Errorf("failed to register node disappearance callback. Error: %s", err) + return nil, errored.Errorf("failed to register node disappearance callback. Error: %s", err) } return m, nil diff --git a/management/src/clusterm/manager/utils.go b/management/src/clusterm/manager/utils.go index ba7d258..6bb4c99 100644 --- a/management/src/clusterm/manager/utils.go +++ b/management/src/clusterm/manager/utils.go @@ -1,22 +1,21 @@ package manager import ( - "fmt" - log "github.com/Sirupsen/logrus" "github.com/contiv/cluster/management/src/inventory" + "github.com/contiv/errored" ) func nodeNotExistsError(name string) error { - return fmt.Errorf("node with name %q doesn't exists", name) + return errored.Errorf("node with name %q doesn't exists", name) } func nodeConfigNotExistsError(name string) error { - return fmt.Errorf("the configuration info for node %q doesn't exist", name) + return errored.Errorf("the configuration info for node %q doesn't exist", name) } func nodeInventoryNotExistsError(name string) error { - return fmt.Errorf("the inventory info for node %q doesn't exist", name) + return errored.Errorf("the inventory info for node %q doesn't exist", name) } func (m *Manager) findNode(name string) (*node, error) { diff --git a/management/src/collins/client.go b/management/src/collins/client.go index c2674eb..b1024ca 100644 --- a/management/src/collins/client.go +++ b/management/src/collins/client.go @@ -4,13 +4,13 @@ package collins import ( "encoding/json" - "fmt" "io/ioutil" "net/http" "net/url" "strings" log "github.com/Sirupsen/logrus" + "github.com/contiv/errored" ) // Config denotes the configuration for collins client @@ -90,7 +90,7 @@ func (c *Client) CreateAsset(tag, status string) error { if err != nil { body = []byte{} } - return fmt.Errorf("status code %d unexpected. Response body: %q", + return errored.Errorf("status code %d unexpected. Response body: %q", resp.StatusCode, body) } @@ -117,11 +117,11 @@ func (c *Client) GetAsset(tag string) (Asset, error) { body, err := ioutil.ReadAll(resp.Body) if err != nil { - return Asset{}, fmt.Errorf("failed to read response body. Error: %s", err) + return Asset{}, errored.Errorf("failed to read response body. Error: %s", err) } if resp.StatusCode != http.StatusOK { - return Asset{}, fmt.Errorf("status code %d unexpected. Response body: %q", + return Asset{}, errored.Errorf("status code %d unexpected. Response body: %q", resp.StatusCode, body) } @@ -132,7 +132,7 @@ func (c *Client) GetAsset(tag string) (Asset, error) { } `json:"data"` }{} if err := json.Unmarshal(body, collinsResp); err != nil { - return Asset{}, fmt.Errorf("failed to unmarshal response. Error: %s", err) + return Asset{}, errored.Errorf("failed to unmarshal response. Error: %s", err) } log.Debugf("collins asset: %+v", collinsResp.Data.Asset) @@ -155,11 +155,11 @@ func (c *Client) GetAllAssets() ([]Asset, error) { body, err := ioutil.ReadAll(resp.Body) if err != nil { - return nil, fmt.Errorf("failed to read response body. Error: %s", err) + return nil, errored.Errorf("failed to read response body. Error: %s", err) } if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("status code %d unexpected. Response body: %q", + return nil, errored.Errorf("status code %d unexpected. Response body: %q", resp.StatusCode, body) } @@ -172,7 +172,7 @@ func (c *Client) GetAllAssets() ([]Asset, error) { } `json:"data"` }{} if err := json.Unmarshal(body, collinsResp); err != nil { - return nil, fmt.Errorf("failed to unmarshal response. Error: %s", err) + return nil, errored.Errorf("failed to unmarshal response. Error: %s", err) } assets := []Asset{} @@ -209,7 +209,7 @@ func (c *Client) CreateState(name, description, status string) error { if err != nil { body = []byte{} } - return fmt.Errorf("status code %d unexpected. Response body: %q", + return errored.Errorf("status code %d unexpected. Response body: %q", resp.StatusCode, body) } @@ -222,7 +222,7 @@ func (c *Client) CreateState(name, description, status string) error { // AddAssetLog creates a log entry for an asset func (c *Client) AddAssetLog(tag, mtype, message string) error { - return fmt.Errorf("not implemented") + return errored.Errorf("not implemented") } // SetAssetStatus sets the status of an asset @@ -249,7 +249,7 @@ func (c *Client) SetAssetStatus(tag, status, state, reason string) error { if err != nil { body = []byte{} } - return fmt.Errorf("status code %d unexpected. Response body: %q", + return errored.Errorf("status code %d unexpected. Response body: %q", resp.StatusCode, body) } diff --git a/management/src/configuration/ansible.go b/management/src/configuration/ansible.go index 813819e..01f635c 100644 --- a/management/src/configuration/ansible.go +++ b/management/src/configuration/ansible.go @@ -2,11 +2,11 @@ package configuration import ( "encoding/json" - "fmt" "io" "strings" "github.com/contiv/cluster/management/src/ansible" + "github.com/contiv/errored" "github.com/imdario/mergo" ) @@ -96,17 +96,17 @@ func mergeExtraVars(dst, src string) (string, error) { ) if err := json.Unmarshal([]byte(dst), &d); err != nil { - return "", fmt.Errorf("failed to unmarshal dest extra vars %q. Error: %v", dst, err) + return "", errored.Errorf("failed to unmarshal dest extra vars %q. Error: %v", dst, err) } if err := json.Unmarshal([]byte(src), &s); err != nil { - return "", fmt.Errorf("failed to unmarshal src extra vars %q. Error: %v", src, err) + return "", errored.Errorf("failed to unmarshal src extra vars %q. Error: %v", src, err) } if err := mergo.MergeWithOverwrite(&d, &s); err != nil { - return "", fmt.Errorf("failed to merge extra vars, dst: %q src: %q. Error: %v", dst, src, err) + return "", errored.Errorf("failed to merge extra vars, dst: %q src: %q. Error: %v", dst, src, err) } o, err := json.Marshal(d) if err != nil { - return "", fmt.Errorf("failed to marshal resulting extra vars %q. Error: %v", o, err) + return "", errored.Errorf("failed to marshal resulting extra vars %q. Error: %v", o, err) } return string(o), nil diff --git a/management/src/inventory/asset.go b/management/src/inventory/asset.go index 5a7ad6d..a01567a 100644 --- a/management/src/inventory/asset.go +++ b/management/src/inventory/asset.go @@ -2,11 +2,11 @@ package inventory import ( "encoding/json" - "fmt" "strings" log "github.com/Sirupsen/logrus" "github.com/contiv/cluster/management/src/collins" + "github.com/contiv/errored" ) var description = map[AssetState]string{ @@ -161,11 +161,11 @@ func (a *Asset) SetStatus(status AssetStatus, state AssetState) error { } if _, ok := lifecycleStatus[a.status][status]; !ok && a.status != status { - return fmt.Errorf("transition from %q to %q is not allowed", a.status, status) + return errored.Errorf("transition from %q to %q is not allowed", a.status, status) } if _, ok := lifecycleStates[status][state]; !ok { - return fmt.Errorf("%q is not a valid state when asset is in %q status", state, status) + return errored.Errorf("%q is not a valid state when asset is in %q status", state, status) } if err := a.client.SetAssetStatus(a.name, status.String(), state.String(), description[state]); err != nil { diff --git a/management/src/inventory/asset_test.go b/management/src/inventory/asset_test.go index e7c0167..4215768 100644 --- a/management/src/inventory/asset_test.go +++ b/management/src/inventory/asset_test.go @@ -3,12 +3,12 @@ package inventory import ( - "fmt" "strings" "testing" "github.com/contiv/cluster/management/src/collins" "github.com/contiv/cluster/management/src/mock" + "github.com/contiv/errored" "github.com/golang/mock/gomock" . "gopkg.in/check.v1" ) @@ -56,7 +56,7 @@ func (s *inventorySuite) TestNewAssetCreateFailure(c *C) { prevState: Unknown, } mClient.EXPECT().CreateAsset(eAsset.name, - eAsset.status.String()).Return(fmt.Errorf("test error")) + eAsset.status.String()).Return(errored.Errorf("test error")) _, err := NewAsset(mClient, eAsset.name) c.Assert(err, NotNil) } @@ -76,7 +76,7 @@ func (s *inventorySuite) TestNewAssetSetStatusFailure(c *C) { } mClient.EXPECT().CreateAsset(eAsset.name, eAsset.status.String()) mClient.EXPECT().SetAssetStatus(eAsset.name, eAsset.status.String(), - eAsset.state.String(), description[eAsset.state]).Return(fmt.Errorf("test error")) + eAsset.state.String(), description[eAsset.state]).Return(errored.Errorf("test error")) _, err := NewAsset(mClient, eAsset.name) c.Assert(err, NotNil) } @@ -121,7 +121,7 @@ func (s *inventorySuite) TestNewAssetFromCollinsGetFailure(c *C) { state: Disappeared, prevState: Unknown, } - mClient.EXPECT().GetAsset(eAsset.name).Return(collins.Asset{}, fmt.Errorf("test failure")) + mClient.EXPECT().GetAsset(eAsset.name).Return(collins.Asset{}, errored.Errorf("test failure")) _, err := NewAssetFromCollins(mClient, eAsset.name) c.Assert(err, NotNil) } @@ -242,7 +242,7 @@ func (s *inventorySuite) TestSetStatusSetFailure(c *C) { prevState: Unknown, } mClient.EXPECT().SetAssetStatus(asset.name, Provisioning.String(), - Discovered.String(), description[asset.state]).Return(fmt.Errorf("test failure")) + Discovered.String(), description[asset.state]).Return(errored.Errorf("test failure")) err := asset.SetStatus(Provisioning, Discovered) c.Assert(err, NotNil) c.Assert(asset, DeepEquals, eAsset) diff --git a/management/src/inventory/collins.go b/management/src/inventory/collins.go index 7700e44..f7d7d70 100644 --- a/management/src/inventory/collins.go +++ b/management/src/inventory/collins.go @@ -1,9 +1,8 @@ package inventory import ( - "fmt" - "github.com/contiv/cluster/management/src/collins" + "github.com/contiv/errored" ) // CollinsSubsys implements the inventory sub-system for the collins inventory management database @@ -22,7 +21,7 @@ func NewCollinsSubsys(config *collins.Config) (*CollinsSubsys, error) { // create the customs states in collins for state, desc := range description { if err := ci.client.CreateState(state.String(), desc, Any.String()); err != nil { - return nil, fmt.Errorf("failed to create state %q in collins. Error: %s", state, err) + return nil, errored.Errorf("failed to create state %q in collins. Error: %s", state, err) } } @@ -37,7 +36,7 @@ func NewCollinsSubsys(config *collins.Config) (*CollinsSubsys, error) { err error ) if a, err = NewAssetFromCollins(ci.client, ca.Tag); err != nil { - return nil, fmt.Errorf("failed to restore host %q from collins. Error: %s", ca.Tag, err) + return nil, errored.Errorf("failed to restore host %q from collins. Error: %s", ca.Tag, err) } ci.hosts[ca.Tag] = a } diff --git a/management/src/inventory/consts.go b/management/src/inventory/consts.go index 9486798..fb5214d 100644 --- a/management/src/inventory/consts.go +++ b/management/src/inventory/consts.go @@ -2,7 +2,7 @@ package inventory -import "fmt" +import "github.com/contiv/errored" // AssetStatus enumerates all the possible lifecycle status of asset in collins type AssetStatus int @@ -55,6 +55,6 @@ const ( ) var ( - errAssetExists = func(tag string) error { return fmt.Errorf("asset %q already exists", tag) } - errAssetNotExists = func(tag string) error { return fmt.Errorf("asset %q doesn't exists", tag) } + errAssetExists = func(tag string) error { return errored.Errorf("asset %q already exists", tag) } + errAssetNotExists = func(tag string) error { return errored.Errorf("asset %q doesn't exists", tag) } ) diff --git a/management/src/monitor/serf.go b/management/src/monitor/serf.go index 8a998c9..65831e9 100644 --- a/management/src/monitor/serf.go +++ b/management/src/monitor/serf.go @@ -2,10 +2,10 @@ package monitor import ( "encoding/json" - "fmt" "os/exec" log "github.com/Sirupsen/logrus" + "github.com/contiv/errored" "github.com/mapuri/serf/client" "github.com/mapuri/serfer" ) @@ -73,7 +73,7 @@ func (sm *SerfSubsys) RegisterCb(e EventType, cb EventCb) error { sm.disappearedCb = cb return nil } - return fmt.Errorf("Unsupported event type: %d", e) + return errored.Errorf("Unsupported event type: %d", e) } // Start implements the start interface of monitoring sub-system From fc5edfc73cea0a579b388523dee164f7ab8c11bc Mon Sep 17 00:00:00 2001 From: Madhav Puri Date: Tue, 22 Mar 2016 22:23:44 -0700 Subject: [PATCH 2/4] update godeps for contiv/errored Signed-off-by: Madhav Puri --- management/src/Godeps/Godeps.json | 21 ++- .../github.com/contiv/errored/.travis.yml | 5 + .../vendor/github.com/contiv/errored/LICENSE | 13 ++ .../github.com/contiv/errored/README.md | 44 +++++ .../github.com/contiv/errored/errored.go | 161 ++++++++++++++++++ 5 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 management/src/vendor/github.com/contiv/errored/.travis.yml create mode 100644 management/src/vendor/github.com/contiv/errored/LICENSE create mode 100644 management/src/vendor/github.com/contiv/errored/README.md create mode 100644 management/src/vendor/github.com/contiv/errored/errored.go diff --git a/management/src/Godeps/Godeps.json b/management/src/Godeps/Godeps.json index f38a153..fdf1aef 100644 --- a/management/src/Godeps/Godeps.json +++ b/management/src/Godeps/Godeps.json @@ -1,8 +1,17 @@ { "ImportPath": "github.com/contiv/cluster/management/src", - "GoVersion": "go1.5", + "GoVersion": "go1.6", + "GodepVersion": "v60", "Packages": [ - "./..." + "github.com/contiv/cluster/management/src/ansible", + "github.com/contiv/cluster/management/src/clusterctl", + "github.com/contiv/cluster/management/src/clusterm", + "github.com/contiv/cluster/management/src/clusterm/manager", + "github.com/contiv/cluster/management/src/collins", + "github.com/contiv/cluster/management/src/configuration", + "github.com/contiv/cluster/management/src/inventory", + "github.com/contiv/cluster/management/src/monitor", + "github.com/contiv/cluster/management/src/systemtests" ], "Deps": [ { @@ -23,6 +32,10 @@ "Comment": "1.2.0-143-ga65b733", "Rev": "a65b733b303f0055f8d324d805f393cd3e7a7904" }, + { + "ImportPath": "github.com/contiv/errored", + "Rev": "01a98ff0a680ae5702f3e07e03b11cf31ca69108" + }, { "ImportPath": "github.com/contiv/systemtests-utils", "Rev": "c8687a787fd4e395fa2285abb2c03ccef80402c7" @@ -124,6 +137,10 @@ "ImportPath": "golang.org/x/crypto/ssh", "Rev": "7b85b097bf7527677d54d3220065e966a0e3b613" }, + { + "ImportPath": "golang.org/x/crypto/ssh/terminal", + "Rev": "7b85b097bf7527677d54d3220065e966a0e3b613" + }, { "ImportPath": "gopkg.in/check.v1", "Rev": "11d3bc7aa68e238947792f30573146a3231fc0f1" diff --git a/management/src/vendor/github.com/contiv/errored/.travis.yml b/management/src/vendor/github.com/contiv/errored/.travis.yml new file mode 100644 index 0000000..e7efe16 --- /dev/null +++ b/management/src/vendor/github.com/contiv/errored/.travis.yml @@ -0,0 +1,5 @@ +language: go + +go: + - 1.6 + - tip diff --git a/management/src/vendor/github.com/contiv/errored/LICENSE b/management/src/vendor/github.com/contiv/errored/LICENSE new file mode 100644 index 0000000..85c2623 --- /dev/null +++ b/management/src/vendor/github.com/contiv/errored/LICENSE @@ -0,0 +1,13 @@ +Copyright 2016 Cisco Systems Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/management/src/vendor/github.com/contiv/errored/README.md b/management/src/vendor/github.com/contiv/errored/README.md new file mode 100644 index 0000000..798f55d --- /dev/null +++ b/management/src/vendor/github.com/contiv/errored/README.md @@ -0,0 +1,44 @@ +[![ReportCard][ReportCard-Image]][ReportCard-URL] [![Build][Build-Status-Image]][Build-Status-URL] [![GoDoc][GoDoc-Image]][GoDoc-URL] + +# Errored: flexible error messages for golang + +Package errored implements specialized errors for golang that come with: + +* Debug and Trace modes + * Debug emits the location the error was created, Trace emits the whole stack. +* Error combination + * Make two errors into one; carries the trace information for both errors with it! + +Use it just like `fmt`: + +```go +package main + +import "github.com/contiv/errored" + +func main() { + err := errored.Errorf("a message") + err.SetDebug(true) + err.Error() // => "a message [ ]" + err2 := errored.Errorf("another message") + combined := err.Combine(err2) + combined.SetTrace(true) + combined.Error() // => "a message: another message" + two stack traces +} +``` + +## Authors: + +* Madhav Puri +* Erik Hollensbe + +## Sponsorship + +Project Contiv is sponsored by Cisco Systems, Inc. + +[ReportCard-URL]: https://goreportcard.com/report/github.com/contiv/errored +[ReportCard-Image]: http://goreportcard.com/badge/contiv/errored +[Build-Status-URL]: http://travis-ci.org/contiv/errored +[Build-Status-Image]: https://travis-ci.org/contiv/errored.svg?branch=master +[GoDoc-URL]: https://godoc.org/github.com/contiv/errored +[GoDoc-Image]: https://godoc.org/github.com/contiv/errored?status.svg diff --git a/management/src/vendor/github.com/contiv/errored/errored.go b/management/src/vendor/github.com/contiv/errored/errored.go new file mode 100644 index 0000000..2b7ae90 --- /dev/null +++ b/management/src/vendor/github.com/contiv/errored/errored.go @@ -0,0 +1,161 @@ +/*** +Copyright 2014 Cisco Systems Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/* +Package errored implements specialized errors for golang that come with: + + * Debug and Trace modes + * Debug emits the location the error was created, Trace emits the whole stack. + * Error combination + * Make two errors into one; carries the trace information for both errors with it! + +Use it just like `fmt`: + + package main + + import "github.com/contiv/errored" + + func main() { + err := errored.Errorf("a message") + err.SetDebug(true) + err.Error() // => "a message [ ] + err2 := errored.Errorf("another message") + combined := err.Combine(err2) + combined.SetTrace(true) + combined.Error() // => "a message: another message" + two stack traces + } + +*/ +package errored + +import ( + "fmt" + "path" + "runtime" +) + +var ( + // AlwaysTrace will, if set globally, enable tracing on all errors. + AlwaysTrace bool + // AlwaysDebug will, if set globally, enable debug messages on all errors. + AlwaysDebug bool +) + +type errorStack struct { + file string + line int + fun string +} + +// Error is our custom error with description, file, and line. +type Error struct { + Code int + + desc string + stack [][]errorStack + trace bool + debug bool +} + +// SetTrace enables the tracing capabilities of errored's Error struct. +// +// Please note that SetTrace automatically sets debug mode too if enabled. See SetDebug. +func (e *Error) SetTrace(trace bool) { + e.trace = trace + if trace { + e.debug = trace + } +} + +// SetDebug enables the per-error caller information of errored's Error struct. +func (e *Error) SetDebug(debug bool) { + e.debug = debug +} + +// Combine combines two errors into a single one. +func (e *Error) Combine(e2 error) *Error { + if _, ok := e2.(*Error); ok { + return &Error{ + desc: fmt.Sprintf("%v: %v", e.desc, e2.(*Error).desc), + stack: append(e.stack, e2.(*Error).stack...), + } + } + + return &Error{ + desc: fmt.Sprintf("%v: %v", e.desc, e2.Error()), + stack: e.stack, + } +} + +// Error() allows *core.Error to present the `error` interface. +func (e *Error) Error() string { + desc := e.desc + if e.Code != 0 { + desc = fmt.Sprintf("%d %v", e.Code, desc) + } else { + desc = fmt.Sprintf("%v", desc) + } + + if e.trace || AlwaysTrace { + ret := desc + "\n" + + for _, stack := range e.stack { + for _, line := range stack { + ret += fmt.Sprintf("\t%s [%s %d]\n", line.fun, line.file, line.line) + } + } + + return ret + } else if (e.debug || AlwaysDebug) && len(e.stack) > 0 && len(e.stack[0]) > 0 { + return fmt.Sprintf("%s [%s %s %d]", desc, e.stack[0][0].fun, e.stack[0][0].file, e.stack[0][0].line) + } + + return desc +} + +// Errorf returns an *Error based on the format specification provided. +func Errorf(f string, args ...interface{}) *Error { + e := &Error{ + stack: [][]errorStack{}, + desc: fmt.Sprintf(f, args...), + } + + i := 1 + + errors := []errorStack{} + + for { + stack := errorStack{} + pc, file, line, ok := runtime.Caller(i) + if !ok { + break + } + + fun := runtime.FuncForPC(pc) + if fun != nil { + stack.fun = fun.Name() + } + + stack.file = path.Base(file) + stack.line = line + errors = append(errors, stack) + + i++ + } + + e.stack = append(e.stack, errors) + + return e +} From ea90b9fba1529b9b95febd28fb6f380099d30c4f Mon Sep 17 00:00:00 2001 From: Madhav Puri Date: Tue, 22 Mar 2016 22:24:26 -0700 Subject: [PATCH 3/4] add a make target fto save godeps when a new package is imported Signed-off-by: Madhav Puri --- management/src/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/management/src/Makefile b/management/src/Makefile index c052d34..c51b5d1 100644 --- a/management/src/Makefile +++ b/management/src/Makefile @@ -41,6 +41,9 @@ deps: checks: deps clean-generate check-format check-code +godeps-save: + $(all_packages) | xargs godep save + generate: deps @echo "auto generating files" @mkdir -p mock From d4aa4bccd766e8531c533b3fd3599b3d7467c108 Mon Sep 17 00:00:00 2001 From: Madhav Puri Date: Tue, 22 Mar 2016 22:25:25 -0700 Subject: [PATCH 4/4] move error definitions out of consts file other stringer fails due to: https://github.com/golang/go/issues/10249 Signed-off-by: Madhav Puri --- management/src/inventory/asset.go | 5 +++++ management/src/inventory/consts.go | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/management/src/inventory/asset.go b/management/src/inventory/asset.go index a01567a..4ebb7a7 100644 --- a/management/src/inventory/asset.go +++ b/management/src/inventory/asset.go @@ -15,6 +15,11 @@ var description = map[AssetState]string{ Disappeared: "Node has disappeared from monitoring subsystem. Check for possible hardware or network issues", } +var ( + errAssetExists = func(tag string) error { return errored.Errorf("asset %q already exists", tag) } + errAssetNotExists = func(tag string) error { return errored.Errorf("asset %q doesn't exists", tag) } +) + // collinsStatusMap maps the status strings to corresponding enumerated values var collinsStatusMap = map[string]AssetStatus{ Incomplete.String(): Incomplete, diff --git a/management/src/inventory/consts.go b/management/src/inventory/consts.go index fb5214d..f649a9b 100644 --- a/management/src/inventory/consts.go +++ b/management/src/inventory/consts.go @@ -2,8 +2,6 @@ package inventory -import "github.com/contiv/errored" - // AssetStatus enumerates all the possible lifecycle status of asset in collins type AssetStatus int @@ -53,8 +51,3 @@ const ( // Disappeared state denotes that host has disappeared from monitoring subsystem. Disappeared ) - -var ( - errAssetExists = func(tag string) error { return errored.Errorf("asset %q already exists", tag) } - errAssetNotExists = func(tag string) error { return errored.Errorf("asset %q doesn't exists", tag) } -)