commit
cb5b62b3df
7
main.go
7
main.go
|
@ -11,8 +11,9 @@ import (
|
|||
cmderrors "github.com/cloudskiff/driftctl/pkg/cmd/errors"
|
||||
"github.com/cloudskiff/driftctl/pkg/config"
|
||||
"github.com/cloudskiff/driftctl/pkg/version"
|
||||
"github.com/cloudskiff/driftctl/sentry"
|
||||
"github.com/fatih/color"
|
||||
"github.com/getsentry/sentry-go"
|
||||
gosentry "github.com/getsentry/sentry-go"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -47,7 +48,7 @@ func run() int {
|
|||
if cmd.IsReportingEnabled(&driftctlCmd.Command) {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
sentry.CurrentHub().Recover(err)
|
||||
gosentry.CurrentHub().Recover(err)
|
||||
flushSentry()
|
||||
logrus.Fatalf("Captured panic: %s", err)
|
||||
os.Exit(2)
|
||||
|
@ -80,6 +81,6 @@ func run() int {
|
|||
|
||||
func flushSentry() {
|
||||
fmt.Print("Sending error report ...")
|
||||
sentry.Flush(60 * time.Second)
|
||||
gosentry.Flush(60 * time.Second)
|
||||
fmt.Printf(" done, thank you %s\n", color.RedString("❤️"))
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudskiff/driftctl/build"
|
||||
"github.com/cloudskiff/driftctl/pkg/version"
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/cloudskiff/driftctl/sentry"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
@ -99,12 +97,7 @@ func IsReportingEnabled(cmd *cobra.Command) bool {
|
|||
|
||||
func handleReporting(cmd *cobra.Command) error {
|
||||
if IsReportingEnabled(cmd) {
|
||||
logrus.Debug("Enabled error reporting")
|
||||
return sentry.Init(sentry.ClientOptions{
|
||||
Dsn: "https://9f2b735e20bc452387f7fa093f786173@o495597.ingest.sentry.io/5568568",
|
||||
Release: fmt.Sprintf("driftctl@%s", version.Current()),
|
||||
AttachStacktrace: true,
|
||||
})
|
||||
return sentry.Initialize()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ func TestDriftctlCmd_Scan(t *testing.T) {
|
|||
env: map[string]string{
|
||||
"DCTL_FROM": "test",
|
||||
},
|
||||
err: fmt.Errorf("Unable to parse from flag: test\nAccepted schemes are: tfstate://,tfstate+s3://"),
|
||||
err: fmt.Errorf("Unable to parse from flag 'test': \nAccepted schemes are: tfstate://,tfstate+s3://"),
|
||||
},
|
||||
{
|
||||
env: map[string]string{
|
||||
|
@ -111,7 +111,7 @@ func TestDriftctlCmd_Scan(t *testing.T) {
|
|||
env: map[string]string{
|
||||
"DCTL_OUTPUT": "test",
|
||||
},
|
||||
err: fmt.Errorf("Unable to parse output flag: test\nAccepted formats are: console://,json://PATH/TO/FILE.json"),
|
||||
err: fmt.Errorf("Unable to parse output flag 'test': \nAccepted formats are: console://,json://PATH/TO/FILE.json"),
|
||||
},
|
||||
{
|
||||
env: map[string]string{
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package errors
|
||||
|
||||
type UsageError struct {
|
||||
msg string
|
||||
}
|
||||
|
||||
func NewUsageError(msg string) UsageError {
|
||||
return UsageError{msg}
|
||||
}
|
||||
|
||||
func (u UsageError) Error() string {
|
||||
return u.msg
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -20,6 +19,7 @@ import (
|
|||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -53,7 +53,7 @@ func NewScanCmd() *cobra.Command {
|
|||
|
||||
to, _ := cmd.Flags().GetString("to")
|
||||
if !remote.IsSupported(to) {
|
||||
return fmt.Errorf(
|
||||
return errors.Errorf(
|
||||
"unsupported cloud provider '%s'\nValid values are: %s",
|
||||
to,
|
||||
strings.Join(remote.GetSupportedRemotes(), ","),
|
||||
|
@ -71,7 +71,7 @@ func NewScanCmd() *cobra.Command {
|
|||
if filterFlag != "" {
|
||||
expr, err := filter.BuildExpression(filterFlag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse filter expression: %s", err.Error())
|
||||
return errors.Wrap(err, "unable to parse filter expression")
|
||||
}
|
||||
opts.Filter = expr
|
||||
}
|
||||
|
@ -155,10 +155,10 @@ func scanRun(opts *ScanOptions) error {
|
|||
ctl.Stop()
|
||||
}()
|
||||
|
||||
analysis := ctl.Run()
|
||||
analysis, err := ctl.Run()
|
||||
|
||||
if analysis == nil {
|
||||
return errors.New("unable to run driftctl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = output.GetOutput(opts.Output).Write(analysis)
|
||||
|
@ -180,10 +180,15 @@ func parseFromFlag(from []string) ([]config.SupplierConfig, error) {
|
|||
for _, flag := range from {
|
||||
schemePath := strings.Split(flag, "://")
|
||||
if len(schemePath) != 2 || schemePath[1] == "" || schemePath[0] == "" {
|
||||
return nil, fmt.Errorf(
|
||||
"Unable to parse from flag: %s\nAccepted schemes are: %s",
|
||||
return nil, errors.Wrapf(
|
||||
cmderrors.NewUsageError(
|
||||
fmt.Sprintf(
|
||||
"\nAccepted schemes are: %s",
|
||||
strings.Join(supplier.GetSupportedSchemes(), ","),
|
||||
),
|
||||
),
|
||||
"Unable to parse from flag '%s'",
|
||||
flag,
|
||||
strings.Join(supplier.GetSupportedSchemes(), ","),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -191,19 +196,28 @@ func parseFromFlag(from []string) ([]config.SupplierConfig, error) {
|
|||
path := schemePath[1]
|
||||
supplierBackend := strings.Split(scheme, "+")
|
||||
if len(supplierBackend) > 2 {
|
||||
return nil, fmt.Errorf(
|
||||
"Unable to parse from scheme: %s\nAccepted schemes are: %s",
|
||||
return nil, errors.Wrapf(
|
||||
cmderrors.NewUsageError(fmt.Sprintf(
|
||||
"\nAccepted schemes are: %s",
|
||||
strings.Join(supplier.GetSupportedSchemes(), ","),
|
||||
),
|
||||
),
|
||||
"Unable to parse from scheme '%s'",
|
||||
scheme,
|
||||
strings.Join(supplier.GetSupportedSchemes(), ","),
|
||||
)
|
||||
}
|
||||
|
||||
supplierKey := supplierBackend[0]
|
||||
if !supplier.IsSupplierSupported(supplierKey) {
|
||||
return nil, fmt.Errorf(
|
||||
"Unsupported IaC source: %s\nAccepted values are: %s",
|
||||
return nil, errors.Wrapf(
|
||||
cmderrors.NewUsageError(
|
||||
fmt.Sprintf(
|
||||
"\nAccepted values are: %s",
|
||||
strings.Join(supplier.GetSupportedSuppliers(), ","),
|
||||
),
|
||||
),
|
||||
"Unsupported IaC source '%s'",
|
||||
supplierKey,
|
||||
strings.Join(supplier.GetSupportedSuppliers(), ","),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -211,10 +225,15 @@ func parseFromFlag(from []string) ([]config.SupplierConfig, error) {
|
|||
if len(supplierBackend) == 2 {
|
||||
backendString = supplierBackend[1]
|
||||
if !backend.IsSupported(backendString) {
|
||||
return nil, fmt.Errorf(
|
||||
"Unsupported IaC backend: %s\nAccepted values are: %s",
|
||||
return nil, errors.Wrapf(
|
||||
cmderrors.NewUsageError(
|
||||
fmt.Sprintf(
|
||||
"\nAccepted values are: %s",
|
||||
strings.Join(backend.GetSupportedBackends(), ","),
|
||||
),
|
||||
),
|
||||
"Unsupported IaC backend '%s'",
|
||||
backendString,
|
||||
strings.Join(backend.GetSupportedBackends(), ","),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -232,19 +251,29 @@ func parseFromFlag(from []string) ([]config.SupplierConfig, error) {
|
|||
func parseOutputFlag(out string) (*output.OutputConfig, error) {
|
||||
schemeOpts := strings.Split(out, "://")
|
||||
if len(schemeOpts) < 2 || schemeOpts[0] == "" {
|
||||
return nil, fmt.Errorf(
|
||||
"Unable to parse output flag: %s\nAccepted formats are: %s",
|
||||
return nil, errors.Wrapf(
|
||||
cmderrors.NewUsageError(
|
||||
fmt.Sprintf(
|
||||
"\nAccepted formats are: %s",
|
||||
strings.Join(output.SupportedOutputsExample(), ","),
|
||||
),
|
||||
),
|
||||
"Unable to parse output flag '%s'",
|
||||
out,
|
||||
strings.Join(output.SupportedOutputsExample(), ","),
|
||||
)
|
||||
}
|
||||
|
||||
o := schemeOpts[0]
|
||||
if !output.IsSupported(o) {
|
||||
return nil, fmt.Errorf(
|
||||
"Unsupported output '%s'\nValid formats are: %s",
|
||||
return nil, errors.Wrapf(
|
||||
cmderrors.NewUsageError(
|
||||
fmt.Sprintf(
|
||||
"\nValid formats are: %s",
|
||||
strings.Join(output.SupportedOutputsExample(), ","),
|
||||
),
|
||||
),
|
||||
"Unsupported output '%s'",
|
||||
o,
|
||||
strings.Join(output.SupportedOutputsExample(), ","),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -254,10 +283,15 @@ func parseOutputFlag(out string) (*output.OutputConfig, error) {
|
|||
switch o {
|
||||
case output.JSONOutputType:
|
||||
if len(opts) != 1 || opts[0] == "" {
|
||||
return nil, fmt.Errorf(
|
||||
"Invalid json output '%s'\nMust be of kind: %s",
|
||||
return nil, errors.Wrapf(
|
||||
cmderrors.NewUsageError(
|
||||
fmt.Sprintf(
|
||||
"\nMust be of kind: %s",
|
||||
output.Example(output.JSONOutputType),
|
||||
),
|
||||
),
|
||||
"Invalid json output '%s'",
|
||||
out,
|
||||
output.Example(output.JSONOutputType),
|
||||
)
|
||||
}
|
||||
options["path"] = opts[0]
|
||||
|
|
|
@ -67,14 +67,14 @@ func TestScanCmd_Invalid(t *testing.T) {
|
|||
{args: []string{"scan", "-f"}, expected: `flag needs an argument: 'f' in -f`},
|
||||
{args: []string{"scan", "--from"}, expected: `flag needs an argument: --from`},
|
||||
{args: []string{"scan", "--from"}, expected: `flag needs an argument: --from`},
|
||||
{args: []string{"scan", "--from", "tosdgjhgsdhgkjs"}, expected: "Unable to parse from flag: tosdgjhgsdhgkjs\nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "://"}, expected: "Unable to parse from flag: ://\nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "://test"}, expected: "Unable to parse from flag: ://test\nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "tosdgjhgsdhgkjs://"}, expected: "Unable to parse from flag: tosdgjhgsdhgkjs://\nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "terraform+foo+bar://test"}, expected: "Unable to parse from scheme: terraform+foo+bar\nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "unsupported://test"}, expected: "Unsupported IaC source: unsupported\nAccepted values are: tfstate"},
|
||||
{args: []string{"scan", "--from", "tfstate+foobar://test"}, expected: "Unsupported IaC backend: foobar\nAccepted values are: s3"},
|
||||
{args: []string{"scan", "--from", "tfstate:///tmp/test", "--from", "tfstate+toto://test"}, expected: "Unsupported IaC backend: toto\nAccepted values are: s3"},
|
||||
{args: []string{"scan", "--from", "tosdgjhgsdhgkjs"}, expected: "Unable to parse from flag 'tosdgjhgsdhgkjs': \nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "://"}, expected: "Unable to parse from flag '://': \nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "://test"}, expected: "Unable to parse from flag '://test': \nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "tosdgjhgsdhgkjs://"}, expected: "Unable to parse from flag 'tosdgjhgsdhgkjs://': \nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "terraform+foo+bar://test"}, expected: "Unable to parse from scheme 'terraform+foo+bar': \nAccepted schemes are: tfstate://,tfstate+s3://"},
|
||||
{args: []string{"scan", "--from", "unsupported://test"}, expected: "Unsupported IaC source 'unsupported': \nAccepted values are: tfstate"},
|
||||
{args: []string{"scan", "--from", "tfstate+foobar://test"}, expected: "Unsupported IaC backend 'foobar': \nAccepted values are: s3"},
|
||||
{args: []string{"scan", "--from", "tfstate:///tmp/test", "--from", "tfstate+toto://test"}, expected: "Unsupported IaC backend 'toto': \nAccepted values are: s3"},
|
||||
{args: []string{"scan", "--filter", "Type='test'"}, expected: "unable to parse filter expression: SyntaxError: Expected tRbracket, received: tUnknown"},
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ func Test_parseOutputFlag(t *testing.T) {
|
|||
out: "",
|
||||
},
|
||||
want: nil,
|
||||
err: fmt.Errorf("Unable to parse output flag: \nAccepted formats are: console://,json://PATH/TO/FILE.json"),
|
||||
err: fmt.Errorf("Unable to parse output flag '': \nAccepted formats are: console://,json://PATH/TO/FILE.json"),
|
||||
},
|
||||
{
|
||||
name: "test invalid",
|
||||
|
@ -173,7 +173,7 @@ func Test_parseOutputFlag(t *testing.T) {
|
|||
out: "sdgjsdgjsdg",
|
||||
},
|
||||
want: nil,
|
||||
err: fmt.Errorf("Unable to parse output flag: sdgjsdgjsdg\nAccepted formats are: console://,json://PATH/TO/FILE.json"),
|
||||
err: fmt.Errorf("Unable to parse output flag 'sdgjsdgjsdg': \nAccepted formats are: console://,json://PATH/TO/FILE.json"),
|
||||
},
|
||||
{
|
||||
name: "test invalid",
|
||||
|
@ -181,7 +181,7 @@ func Test_parseOutputFlag(t *testing.T) {
|
|||
out: "://",
|
||||
},
|
||||
want: nil,
|
||||
err: fmt.Errorf("Unable to parse output flag: ://\nAccepted formats are: console://,json://PATH/TO/FILE.json"),
|
||||
err: fmt.Errorf("Unable to parse output flag '://': \nAccepted formats are: console://,json://PATH/TO/FILE.json"),
|
||||
},
|
||||
{
|
||||
name: "test unsupported",
|
||||
|
@ -189,7 +189,7 @@ func Test_parseOutputFlag(t *testing.T) {
|
|||
out: "foobar://",
|
||||
},
|
||||
want: nil,
|
||||
err: fmt.Errorf("Unsupported output 'foobar'\nValid formats are: console://,json://PATH/TO/FILE.json"),
|
||||
err: fmt.Errorf("Unsupported output 'foobar': \nValid formats are: console://,json://PATH/TO/FILE.json"),
|
||||
},
|
||||
{
|
||||
name: "test empty json",
|
||||
|
@ -197,7 +197,7 @@ func Test_parseOutputFlag(t *testing.T) {
|
|||
out: "json://",
|
||||
},
|
||||
want: nil,
|
||||
err: fmt.Errorf("Invalid json output 'json://'\nMust be of kind: json://PATH/TO/FILE.json"),
|
||||
err: fmt.Errorf("Invalid json output 'json://': \nMust be of kind: json://PATH/TO/FILE.json"),
|
||||
},
|
||||
{
|
||||
name: "test valid console",
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/cloudskiff/driftctl/pkg/middlewares"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -24,11 +25,10 @@ func NewDriftCTL(remoteSupplier resource.Supplier, iacSupplier resource.Supplier
|
|||
return &DriftCTL{remoteSupplier, iacSupplier, alerter, analyser.NewAnalyzer(alerter), filter}
|
||||
}
|
||||
|
||||
func (d DriftCTL) Run() *analyser.Analysis {
|
||||
func (d DriftCTL) Run() (*analyser.Analysis, error) {
|
||||
remoteResources, resourcesFromState, err := d.scan()
|
||||
if err != nil {
|
||||
logrus.Errorf("Unable to scan resources: %+v", err)
|
||||
return nil
|
||||
return nil, errors.Wrap(err, "Unable to scan resources")
|
||||
}
|
||||
|
||||
middleware := middlewares.NewChain(
|
||||
|
@ -56,21 +56,18 @@ func (d DriftCTL) Run() *analyser.Analysis {
|
|||
logrus.Debug("Ready to run middlewares")
|
||||
err = middleware.Execute(&remoteResources, &resourcesFromState)
|
||||
if err != nil {
|
||||
logrus.Errorf("Unable to run middlewares: %+v", err)
|
||||
return nil
|
||||
return nil, errors.Wrap(err, "Unable to run middlewares")
|
||||
}
|
||||
|
||||
if d.filter != nil {
|
||||
engine := filter.NewFilterEngine(d.filter)
|
||||
remoteResources, err = engine.Run(remoteResources)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
return nil, errors.Wrap(err, "Unable to filter remote resources")
|
||||
}
|
||||
resourcesFromState, err = engine.Run(resourcesFromState)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
return nil, errors.Wrap(err, "Unable to filter state resources")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,11 +77,10 @@ func (d DriftCTL) Run() *analyser.Analysis {
|
|||
analysis, err := d.analyzer.Analyze(remoteResources, resourcesFromState, driftIgnore)
|
||||
|
||||
if err != nil {
|
||||
logrus.Errorf("Unable to analyse resources: %+v", err)
|
||||
return nil
|
||||
return nil, errors.Wrap(err, "Unable to perform resources analysis")
|
||||
}
|
||||
|
||||
return &analysis
|
||||
return &analysis, nil
|
||||
}
|
||||
|
||||
func (d DriftCTL) Stop() {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/cloudskiff/driftctl/pkg/iac/terraform/state/backend"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/iac/config"
|
||||
|
@ -31,7 +32,7 @@ func GetIACSupplier(configs []config.SupplierConfig, library *terraform.Provider
|
|||
chainSupplier := resource.NewChainSupplier()
|
||||
for _, config := range configs {
|
||||
if !IsSupplierSupported(config.Key) {
|
||||
return nil, fmt.Errorf("Unsupported supplier '%s'", config.Key)
|
||||
return nil, errors.Errorf("Unsupported supplier '%s'", config.Key)
|
||||
}
|
||||
|
||||
var supplier resource.Supplier
|
||||
|
@ -40,7 +41,7 @@ func GetIACSupplier(configs []config.SupplierConfig, library *terraform.Provider
|
|||
case state.TerraformStateReaderSupplier:
|
||||
supplier, err = state.NewReader(config, library)
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported supplier '%s'", config.Key)
|
||||
return nil, errors.Errorf("Unsupported supplier '%s'", config.Key)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/iac/config"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var supportedBackends = []string{
|
||||
|
@ -29,7 +29,7 @@ func GetBackend(config config.SupplierConfig) (Backend, error) {
|
|||
backend := config.Backend
|
||||
|
||||
if !IsSupported(backend) {
|
||||
return nil, fmt.Errorf("Unsupported backend '%s'", backend)
|
||||
return nil, errors.Errorf("Unsupported backend '%s'", backend)
|
||||
}
|
||||
|
||||
switch backend {
|
||||
|
@ -38,7 +38,7 @@ func GetBackend(config config.SupplierConfig) (Backend, error) {
|
|||
case backendS3:
|
||||
return NewS3Reader(config.Path)
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported backend '%s'", backend)
|
||||
return nil, errors.Errorf("Unsupported backend '%s'", backend)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3iface"
|
||||
|
@ -24,7 +24,7 @@ func NewS3Reader(path string) (*S3Backend, error) {
|
|||
backend := S3Backend{}
|
||||
bucketPath := strings.Split(path, "/")
|
||||
if len(bucketPath) < 2 {
|
||||
return nil, fmt.Errorf("Unable to parse S3 path: %s. Must be BUCKET_NAME/PATH/TO/OBJECT", path)
|
||||
return nil, errors.Errorf("Unable to parse S3 path: %s. Must be BUCKET_NAME/PATH/TO/OBJECT", path)
|
||||
}
|
||||
bucket := bucketPath[0]
|
||||
key := strings.Join(bucketPath[1:], "/")
|
||||
|
@ -46,7 +46,12 @@ func (s *S3Backend) Read(p []byte) (n int, err error) {
|
|||
if err != nil {
|
||||
requestFailure, ok := err.(s3.RequestFailure)
|
||||
if ok {
|
||||
return 0, fmt.Errorf("Error reading state '%s' from s3 bucket '%s': %s", *s.input.Key, *s.input.Bucket, requestFailure.Message())
|
||||
return 0, errors.Errorf(
|
||||
"Error reading state '%s' from s3 bucket '%s': %s",
|
||||
*s.input.Key,
|
||||
*s.input.Bucket,
|
||||
requestFailure.Message(),
|
||||
)
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
@ -59,5 +64,5 @@ func (s *S3Backend) Close() error {
|
|||
if s.reader != nil {
|
||||
return s.reader.Close()
|
||||
}
|
||||
return fmt.Errorf("Unable to close reader as nothing was opened")
|
||||
return errors.New("Unable to close reader as nothing was opened")
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@ package parallel
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"go.uber.org/atomic"
|
||||
|
@ -91,7 +91,7 @@ func (p *ParallelRunner) Run(runnable func() (interface{}, error)) {
|
|||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
sentry.CurrentHub().Recover(r)
|
||||
p.Stop(fmt.Errorf("A runner routine paniced: %s", r))
|
||||
p.Stop(errors.Errorf("A runner routine paniced: %s", r))
|
||||
}
|
||||
}()
|
||||
res, err := runnable()
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package remote
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/alerter"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var supportedRemotes = []string{
|
||||
|
@ -27,7 +26,7 @@ func Activate(remote string, alerter *alerter.Alerter, providerLibrary *terrafor
|
|||
case aws.RemoteAWSTerraform:
|
||||
return aws.Init(alerter, providerLibrary, supplierLibrary)
|
||||
default:
|
||||
return fmt.Errorf("unsupported remote '%s'", remote)
|
||||
return errors.Errorf("unsupported remote '%s'", remote)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/hashicorp/terraform/helper/hashcode"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (r *AwsRoute) String() string {
|
||||
|
@ -28,7 +29,7 @@ func CalculateRouteID(tableId, CidrBlock, Ipv6CidrBlock *string) (string, error)
|
|||
return fmt.Sprintf("r-%s%d", *tableId, hashcode.String(*Ipv6CidrBlock)), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("invalid route detected for table %s", *tableId)
|
||||
return "", errors.Errorf("invalid route detected for table %s", *tableId)
|
||||
}
|
||||
|
||||
func (r *AwsRoute) NormalizeForState() (resource.Resource, error) {
|
||||
|
|
|
@ -2,9 +2,9 @@ package pkg
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/parallel"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -85,5 +85,5 @@ loop:
|
|||
|
||||
func (s *Scanner) Stop() {
|
||||
logrus.Debug("Stopping scanner")
|
||||
s.runner.Stop(fmt.Errorf("interrupted"))
|
||||
s.runner.Stop(errors.New("interrupted"))
|
||||
}
|
||||
|
|
|
@ -2,13 +2,12 @@ package terraform
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/go-getter"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -46,17 +45,21 @@ func (p *ProviderDownloader) Download(url, path string) error {
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("unsuccessful request to %s: %s", url, resp.Status)
|
||||
return errors.Errorf("unsuccessful request to %s: %s", url, resp.Status)
|
||||
}
|
||||
f, err := ioutil.TempFile("", "terraform-provider")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open temporary file to download from %s", url)
|
||||
return errors.Errorf("failed to open temporary file to download from %s", url)
|
||||
}
|
||||
defer f.Close()
|
||||
defer os.Remove(f.Name())
|
||||
n, err := getter.Copy(p.context, f, resp.Body)
|
||||
if err == nil && n < resp.ContentLength {
|
||||
err = fmt.Errorf("incorrect response size: expected %d bytes, but got %d bytes", resp.ContentLength, n)
|
||||
err = errors.Errorf(
|
||||
"incorrect response size: expected %d bytes, but got %d bytes",
|
||||
resp.ContentLength,
|
||||
n,
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"runtime"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -56,7 +57,10 @@ func (p *ProviderInstaller) Install() (string, error) {
|
|||
}
|
||||
|
||||
if info != nil && info.IsDir() {
|
||||
return "", fmt.Errorf("found directory instead of provider binary in %s", providerPath)
|
||||
return "", errors.Errorf(
|
||||
"found directory instead of provider binary in %s",
|
||||
providerPath,
|
||||
)
|
||||
}
|
||||
|
||||
if info != nil {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package sentry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
cmderrors "github.com/cloudskiff/driftctl/pkg/cmd/errors"
|
||||
"github.com/cloudskiff/driftctl/pkg/version"
|
||||
gosentry "github.com/getsentry/sentry-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var excludedErrorTypes = []error{
|
||||
cmderrors.UsageError{},
|
||||
}
|
||||
|
||||
func Initialize() error {
|
||||
logrus.Debug("Enabled error reporting")
|
||||
return gosentry.Init(gosentry.ClientOptions{
|
||||
Dsn: "https://9f2b735e20bc452387f7fa093f786173@o495597.ingest.sentry.io/5568568",
|
||||
Release: fmt.Sprintf("driftctl@%s", version.Current()),
|
||||
AttachStacktrace: true,
|
||||
})
|
||||
}
|
||||
|
||||
func shouldCaptureException(err error) bool {
|
||||
errType, causeType := reflect.TypeOf(err), reflect.TypeOf(errors.Cause(err))
|
||||
for _, exludedError := range excludedErrorTypes {
|
||||
switch reflect.TypeOf(exludedError) {
|
||||
case errType:
|
||||
return false
|
||||
case causeType:
|
||||
return false
|
||||
default:
|
||||
}
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"error_type": errType,
|
||||
"cause_type": causeType,
|
||||
}).Debug("Sentry captured error")
|
||||
return true
|
||||
}
|
||||
|
||||
func CaptureException(err error) {
|
||||
if shouldCaptureException(err) {
|
||||
gosentry.CaptureException(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package sentry
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
cmderrors "github.com/cloudskiff/driftctl/pkg/cmd/errors"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Test_shouldCaptureException(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
err error
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "should not capture errors.UsageError",
|
||||
err: cmderrors.UsageError{},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "should not capture wrapped errors.UsageError",
|
||||
err: errors.Wrap(cmderrors.UsageError{}, "test"),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "should capture errors.withStack",
|
||||
err: errors.New("test"),
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := shouldCaptureException(tt.err); got != tt.want {
|
||||
t.Errorf("shouldCaptureException() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue