github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/ec2/provider_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package ec2_test 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 "gopkg.in/amz.v3/aws" 13 ec2cloud "gopkg.in/amz.v3/ec2" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/cloud" 17 "github.com/juju/juju/environs" 18 "github.com/juju/juju/environs/context" 19 "github.com/juju/juju/provider/common" 20 "github.com/juju/juju/provider/ec2" 21 coretesting "github.com/juju/juju/testing" 22 ) 23 24 type ProviderSuite struct { 25 testing.IsolationSuite 26 spec environs.CloudSpec 27 provider environs.EnvironProvider 28 } 29 30 var _ = gc.Suite(&ProviderSuite{}) 31 32 func (s *ProviderSuite) SetUpTest(c *gc.C) { 33 s.IsolationSuite.SetUpTest(c) 34 35 credential := cloud.NewCredential( 36 cloud.AccessKeyAuthType, 37 map[string]string{ 38 "access-key": "foo", 39 "secret-key": "bar", 40 }, 41 ) 42 s.spec = environs.CloudSpec{ 43 Type: "ec2", 44 Name: "aws", 45 Region: "us-east-1", 46 Credential: &credential, 47 } 48 49 provider, err := environs.Provider("ec2") 50 c.Assert(err, jc.ErrorIsNil) 51 s.provider = provider 52 } 53 54 func (s *ProviderSuite) TestOpen(c *gc.C) { 55 env, err := environs.Open(s.provider, environs.OpenParams{ 56 Cloud: s.spec, 57 Config: coretesting.ModelConfig(c), 58 }) 59 c.Assert(err, jc.ErrorIsNil) 60 c.Assert(env, gc.NotNil) 61 } 62 63 func (s *ProviderSuite) TestOpenUnknownRegion(c *gc.C) { 64 // This test shows that we do *not* check the region names against 65 // anything in the client. That means that when new regions are 66 // added to AWS, we'll be able to support them. 67 s.spec.Region = "foobar" 68 _, err := environs.Open(s.provider, environs.OpenParams{ 69 Cloud: s.spec, 70 Config: coretesting.ModelConfig(c), 71 }) 72 c.Assert(err, jc.ErrorIsNil) 73 } 74 75 func (s *ProviderSuite) TestOpenKnownRegionInvalidEndpoint(c *gc.C) { 76 s.PatchValue(&aws.Regions, map[string]aws.Region{ 77 "us-east-1": { 78 EC2Endpoint: "https://testing.invalid", 79 }, 80 }) 81 s.spec.Endpoint = "https://us-east-1.aws.amazon.com/v1.2/" 82 83 env, err := environs.Open(s.provider, environs.OpenParams{ 84 Cloud: s.spec, 85 Config: coretesting.ModelConfig(c), 86 }) 87 c.Assert(err, jc.ErrorIsNil) 88 89 ec2Client := ec2.EnvironEC2(env) 90 c.Assert(ec2Client.Region.EC2Endpoint, gc.Equals, "https://testing.invalid") 91 } 92 93 func (s *ProviderSuite) TestOpenKnownRegionValidEndpoint(c *gc.C) { 94 // If the endpoint in the cloudspec is not known to be invalid, 95 // we ignore whatever is in aws.Regions. This way, if the AWS 96 // endpoints do ever change, we can update public-clouds.yaml 97 // and have it picked up. 98 s.PatchValue(&aws.Regions, map[string]aws.Region{ 99 "us-east-1": { 100 EC2Endpoint: "https://testing.invalid", 101 }, 102 }) 103 s.spec.Endpoint = "https://ec2.us-east-1.amazonaws.com" 104 105 env, err := environs.Open(s.provider, environs.OpenParams{ 106 Cloud: s.spec, 107 Config: coretesting.ModelConfig(c), 108 }) 109 c.Assert(err, jc.ErrorIsNil) 110 111 ec2Client := ec2.EnvironEC2(env) 112 c.Assert(ec2Client.Region.EC2Endpoint, gc.Equals, "https://ec2.us-east-1.amazonaws.com") 113 } 114 115 func (s *ProviderSuite) TestOpenMissingCredential(c *gc.C) { 116 s.spec.Credential = nil 117 s.testOpenError(c, s.spec, `validating cloud spec: missing credential not valid`) 118 } 119 120 func (s *ProviderSuite) TestOpenUnsupportedCredential(c *gc.C) { 121 credential := cloud.NewCredential(cloud.UserPassAuthType, map[string]string{}) 122 s.spec.Credential = &credential 123 s.testOpenError(c, s.spec, `validating cloud spec: "userpass" auth-type not supported`) 124 } 125 126 func (s *ProviderSuite) testOpenError(c *gc.C, spec environs.CloudSpec, expect string) { 127 _, err := environs.Open(s.provider, environs.OpenParams{ 128 Cloud: spec, 129 Config: coretesting.ModelConfig(c), 130 }) 131 c.Assert(err, gc.ErrorMatches, expect) 132 } 133 134 func (s *ProviderSuite) TestVerifyCredentialsErrs(c *gc.C) { 135 env, err := environs.Open(s.provider, environs.OpenParams{ 136 Cloud: s.spec, 137 Config: coretesting.ModelConfig(c), 138 }) 139 c.Assert(err, jc.ErrorIsNil) 140 c.Assert(env, gc.NotNil) 141 142 err = ec2.VerifyCredentials(env, context.NewCloudCallContext()) 143 c.Assert(err, gc.Not(jc.ErrorIsNil)) 144 c.Assert(err, gc.Not(jc.Satisfies), common.IsCredentialNotValid) 145 } 146 147 func (s *ProviderSuite) TestMaybeConvertCredentialErrorIgnoresNil(c *gc.C) { 148 err := ec2.MaybeConvertCredentialError(nil, context.NewCloudCallContext()) 149 c.Assert(err, jc.ErrorIsNil) 150 } 151 152 func (s *ProviderSuite) TestMaybeConvertCredentialErrorConvertsCredentialRelatedFailures(c *gc.C) { 153 for _, code := range []string{ 154 "AuthFailure", 155 "InvalidClientTokenId", 156 "MissingAuthenticationToken", 157 "Blocked", 158 "CustomerKeyHasBeenRevoked", 159 "PendingVerification", 160 "SignatureDoesNotMatch", 161 } { 162 err := ec2.MaybeConvertCredentialError(&ec2cloud.Error{Code: code}, context.NewCloudCallContext()) 163 c.Assert(err, gc.NotNil) 164 c.Assert(err, jc.Satisfies, common.IsCredentialNotValid) 165 } 166 } 167 168 func (s *ProviderSuite) TestMaybeConvertCredentialErrorAppendsAuthorisationFailureMessage(c *gc.C) { 169 for _, code := range []string{ 170 "OptInRequired", 171 "UnauthorizedOperation", 172 } { 173 err := ec2.MaybeConvertCredentialError(&ec2cloud.Error{Code: code}, context.NewCloudCallContext()) 174 c.Assert(err, gc.NotNil) 175 c.Assert(err, gc.Not(jc.Satisfies), common.IsCredentialNotValid) 176 c.Assert(err.Error(), jc.Contains, fmt.Sprintf("\nPlease subscribe to the requested Amazon service. \n"+ 177 "You are currently not authorized to use it.\n"+ 178 "New Amazon accounts might take some time to be activated while \n"+ 179 "your details are being verified.: (%v)", code)) 180 } 181 } 182 183 func (s *ProviderSuite) TestMaybeConvertCredentialErrorHandlesOtherProviderErrors(c *gc.C) { 184 // Any other ec2.Error is returned unwrapped. 185 err := ec2.MaybeConvertCredentialError(&ec2cloud.Error{Code: "DryRunOperation"}, context.NewCloudCallContext()) 186 c.Assert(err, gc.Not(jc.ErrorIsNil)) 187 c.Assert(err, gc.Not(jc.Satisfies), common.IsCredentialNotValid) 188 } 189 190 func (s *ProviderSuite) TestConvertedCredentialError(c *gc.C) { 191 // Trace() will keep error type 192 inner := ec2.MaybeConvertCredentialError(&ec2cloud.Error{Code: "Blocked"}, context.NewCloudCallContext()) 193 traced := errors.Trace(inner) 194 c.Assert(traced, gc.NotNil) 195 c.Assert(traced, jc.Satisfies, common.IsCredentialNotValid) 196 197 // Annotate() will keep error type 198 annotated := errors.Annotate(inner, "annotation") 199 c.Assert(annotated, gc.NotNil) 200 c.Assert(annotated, jc.Satisfies, common.IsCredentialNotValid) 201 202 // Running a CredentialNotValid through conversion call again is a no-op. 203 again := ec2.MaybeConvertCredentialError(inner, context.NewCloudCallContext()) 204 c.Assert(again, gc.NotNil) 205 c.Assert(again, jc.Satisfies, common.IsCredentialNotValid) 206 c.Assert(again.Error(), jc.Contains, "\nYour Amazon account is currently blocked.: (Blocked)") 207 208 // Running an annotated CredentialNotValid through conversion call again is a no-op too. 209 againAnotated := ec2.MaybeConvertCredentialError(annotated, context.NewCloudCallContext()) 210 c.Assert(againAnotated, gc.NotNil) 211 c.Assert(againAnotated, jc.Satisfies, common.IsCredentialNotValid) 212 c.Assert(againAnotated.Error(), jc.Contains, "\nYour Amazon account is currently blocked.: (Blocked)") 213 }