github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/azure/internal/errorutils/errors.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package errorutils 5 6 import ( 7 "github.com/Azure/go-autorest/autorest" 8 "github.com/Azure/go-autorest/autorest/azure" 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 12 "github.com/juju/juju/environs/context" 13 "github.com/juju/juju/provider/common" 14 ) 15 16 var logger = loggo.GetLogger("juju.provider.azure") 17 18 // ServiceError returns the *azure.ServiceError underlying the 19 // supplied error, if any, and a bool indicating whether one 20 // was found. 21 func ServiceError(err error) (*azure.ServiceError, bool) { 22 err = errors.Cause(err) 23 if d, ok := err.(autorest.DetailedError); ok { 24 err = d.Original 25 } 26 if r, ok := err.(*azure.RequestError); ok { 27 return r.ServiceError, true 28 } 29 // The error Azure gives us back can also be a struct 30 // not a pointer. 31 if r, ok := err.(azure.RequestError); ok { 32 return r.ServiceError, true 33 } 34 return nil, false 35 } 36 37 // HandleCredentialError determines if given error relates to invalid credential. 38 // If it is, the credential is invalidated. 39 // Original error is returned untouched. 40 func HandleCredentialError(err error, ctx context.ProviderCallContext) error { 41 MaybeInvalidateCredential(err, ctx) 42 return err 43 } 44 45 // MaybeInvalidateCredential determines if given error is related to authentication/authorisation failures. 46 // If an error is related to an invalid credential, then this call will try to invalidate that credential as well. 47 func MaybeInvalidateCredential(err error, ctx context.ProviderCallContext) bool { 48 if ctx == nil { 49 return false 50 } 51 if !hasDenialStatusCode(err) { 52 return false 53 } 54 55 invalidateErr := ctx.InvalidateCredential("azure cloud denied access") 56 if invalidateErr != nil { 57 logger.Warningf("could not invalidate stored azure cloud credential on the controller: %v", invalidateErr) 58 } 59 return true 60 } 61 62 func hasDenialStatusCode(err error) bool { 63 if err == nil { 64 return false 65 } 66 67 if d, ok := errors.Cause(err).(autorest.DetailedError); ok { 68 if d.Response != nil { 69 return common.AuthorisationFailureStatusCodes.Contains(d.Response.StatusCode) 70 } 71 return common.AuthorisationFailureStatusCodes.Contains(d.StatusCode.(int)) 72 } 73 return false 74 }