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  }