github.com/thiagoyeds/go-cloud@v0.26.0/runtimevar/awsparamstore/awsparamstore_test.go (about) 1 // Copyright 2018 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package awsparamstore 16 17 import ( 18 "context" 19 "errors" 20 "os" 21 "testing" 22 23 ssmv2 "github.com/aws/aws-sdk-go-v2/service/ssm" 24 "github.com/aws/aws-sdk-go/aws" 25 "github.com/aws/aws-sdk-go/aws/awserr" 26 "github.com/aws/aws-sdk-go/aws/client" 27 "github.com/aws/aws-sdk-go/aws/session" 28 "github.com/aws/aws-sdk-go/service/ssm" 29 "github.com/aws/smithy-go" 30 "gocloud.dev/internal/testing/setup" 31 "gocloud.dev/runtimevar" 32 "gocloud.dev/runtimevar/driver" 33 "gocloud.dev/runtimevar/drivertest" 34 ) 35 36 // This constant records the region used for the last --record. 37 // If you want to use --record mode, 38 // 1. Update this constant to your AWS region. 39 // TODO(issue #300): Use Terraform to get this. 40 const region = "us-east-2" 41 42 type harness struct { 43 useV2 bool 44 session client.ConfigProvider 45 clientV2 *ssmv2.Client 46 closer func() 47 } 48 49 func newHarness(t *testing.T) (drivertest.Harness, error) { 50 sess, _, done, _ := setup.NewAWSSession(context.Background(), t, region) 51 return &harness{useV2: false, session: sess, closer: done}, nil 52 } 53 54 func newHarnessV2(t *testing.T) (drivertest.Harness, error) { 55 cfg, _, done, _ := setup.NewAWSv2Config(context.Background(), t, region) 56 return &harness{useV2: true, clientV2: ssmv2.NewFromConfig(cfg), closer: done}, nil 57 } 58 59 func (h *harness) MakeWatcher(ctx context.Context, name string, decoder *runtimevar.Decoder) (driver.Watcher, error) { 60 return newWatcher(h.useV2, h.session, h.clientV2, name, decoder, nil), nil 61 } 62 63 func (h *harness) CreateVariable(ctx context.Context, name string, val []byte) error { 64 if h.useV2 { 65 _, err := h.clientV2.PutParameter(ctx, &ssmv2.PutParameterInput{ 66 Name: aws.String(name), 67 Type: "String", 68 Value: aws.String(string(val)), 69 Overwrite: true, 70 }) 71 return err 72 } 73 svc := ssm.New(h.session) 74 _, err := svc.PutParameter(&ssm.PutParameterInput{ 75 Name: aws.String(name), 76 Type: aws.String("String"), 77 Value: aws.String(string(val)), 78 Overwrite: aws.Bool(true), 79 }) 80 return err 81 } 82 83 func (h *harness) UpdateVariable(ctx context.Context, name string, val []byte) error { 84 return h.CreateVariable(ctx, name, val) 85 } 86 87 func (h *harness) DeleteVariable(ctx context.Context, name string) error { 88 if h.useV2 { 89 _, err := h.clientV2.DeleteParameter(ctx, &ssmv2.DeleteParameterInput{Name: aws.String(name)}) 90 return err 91 } 92 svc := ssm.New(h.session) 93 _, err := svc.DeleteParameter(&ssm.DeleteParameterInput{Name: aws.String(name)}) 94 return err 95 } 96 97 func (h *harness) Close() { 98 h.closer() 99 } 100 101 func (h *harness) Mutable() bool { return true } 102 103 func TestConformance(t *testing.T) { 104 drivertest.RunConformanceTests(t, newHarness, []drivertest.AsTest{verifyAs{useV2: false}}) 105 } 106 107 func TestConformanceV2(t *testing.T) { 108 drivertest.RunConformanceTests(t, newHarnessV2, []drivertest.AsTest{verifyAs{useV2: true}}) 109 } 110 111 type verifyAs struct { 112 useV2 bool 113 } 114 115 func (verifyAs) Name() string { 116 return "verify As" 117 } 118 119 func (v verifyAs) SnapshotCheck(s *runtimevar.Snapshot) error { 120 if v.useV2 { 121 var getParam *ssmv2.GetParameterOutput 122 if !s.As(&getParam) { 123 return errors.New("Snapshot.As failed for GetParameterOutput") 124 } 125 var descParam *ssmv2.DescribeParametersOutput 126 if !s.As(&descParam) { 127 return errors.New("Snapshot.As failed for DescribeParametersOutput") 128 } 129 return nil 130 } 131 var getParam *ssm.GetParameterOutput 132 if !s.As(&getParam) { 133 return errors.New("Snapshot.As failed for GetParameterOutput") 134 } 135 var descParam *ssm.DescribeParametersOutput 136 if !s.As(&descParam) { 137 return errors.New("Snapshot.As failed for DescribeParametersOutput") 138 } 139 return nil 140 } 141 142 func (va verifyAs) ErrorCheck(v *runtimevar.Variable, err error) error { 143 if va.useV2 { 144 var e smithy.APIError 145 if !v.ErrorAs(err, &e) { 146 return errors.New("Keeper.ErrorAs failed") 147 } 148 return nil 149 } 150 var e awserr.Error 151 if !v.ErrorAs(err, &e) { 152 return errors.New("runtimevar.ErrorAs failed") 153 } 154 return nil 155 } 156 157 // Paramstore-specific tests. 158 159 func TestEquivalentError(t *testing.T) { 160 tests := []struct { 161 Err1, Err2 error 162 Want bool 163 }{ 164 {Err1: errors.New("not aws"), Err2: errors.New("not aws"), Want: true}, 165 {Err1: errors.New("not aws"), Err2: errors.New("not aws but different")}, 166 {Err1: errors.New("not aws"), Err2: awserr.New("code1", "fail", nil)}, 167 {Err1: awserr.New("code1", "fail", nil), Err2: awserr.New("code2", "fail", nil)}, 168 {Err1: awserr.New("code1", "fail", nil), Err2: awserr.New("code1", "fail", nil), Want: true}, 169 } 170 171 for _, test := range tests { 172 got := equivalentError(test.Err1, test.Err2) 173 if got != test.Want { 174 t.Errorf("%v vs %v: got %v want %v", test.Err1, test.Err2, got, test.Want) 175 } 176 } 177 } 178 179 func TestNoConnectionError(t *testing.T) { 180 prevAccessKey := os.Getenv("AWS_ACCESS_KEY") 181 prevSecretKey := os.Getenv("AWS_SECRET_KEY") 182 prevRegion := os.Getenv("AWS_REGION") 183 os.Setenv("AWS_ACCESS_KEY", "myaccesskey") 184 os.Setenv("AWS_SECRET_KEY", "mysecretkey") 185 os.Setenv("AWS_REGION", "us-east-1") 186 defer func() { 187 os.Setenv("AWS_ACCESS_KEY", prevAccessKey) 188 os.Setenv("AWS_SECRET_KEY", prevSecretKey) 189 os.Setenv("AWS_REGION", prevRegion) 190 }() 191 sess, err := session.NewSession() 192 if err != nil { 193 t.Fatal(err) 194 } 195 196 v, err := OpenVariable(sess, "variable-name", nil, nil) 197 if err != nil { 198 t.Fatal(err) 199 } 200 defer v.Close() 201 _, err = v.Watch(context.Background()) 202 if err == nil { 203 t.Error("got nil want error") 204 } 205 } 206 207 func TestOpenVariable(t *testing.T) { 208 tests := []struct { 209 URL string 210 WantErr bool 211 }{ 212 // OK. 213 {"awsparamstore://myvar", false}, 214 // OK, setting region. 215 {"awsparamstore://myvar?region=us-west-1", false}, 216 // OK, setting decoder. 217 {"awsparamstore://myvar?decoder=string", false}, 218 // Invalid decoder. 219 {"awsparamstore://myvar?decoder=notadecoder", true}, 220 // Invalid parameter. 221 {"awsparamstore://myvar?param=value", true}, 222 // OK, using SDK V2. 223 {"awsparamstore://myvar?decoder=string&awssdk=v2", false}, 224 } 225 226 ctx := context.Background() 227 for _, test := range tests { 228 v, err := runtimevar.OpenVariable(ctx, test.URL) 229 if (err != nil) != test.WantErr { 230 t.Errorf("%s: got error %v, want error %v", test.URL, err, test.WantErr) 231 } 232 if err == nil { 233 v.Close() 234 } 235 } 236 }