// nextPageTokens returns the tokens to use when asking for the next page of // data. func (r *Request) nextPageTokens() []interface{} { if r.Operation.Paginator == nil { return nil } if r.Operation.TruncationToken != "" { tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken) if len(tr) == 0 { return nil } switch v := tr[0].(type) { case *bool: if !aws.BoolValue(v) { return nil } case bool: if v == false { return nil } } } tokens := []interface{}{} for _, outToken := range r.Operation.OutputTokens { v, _ := awsutil.ValuesAtPath(r.Data, outToken) if len(v) > 0 { tokens = append(tokens, v[0]) } } return tokens }
// Wait waits for an operation to complete, expire max attempts, or fail. Error // is returned if the operation fails. func (w *Waiter) Wait() error { client := reflect.ValueOf(w.Client) in := reflect.ValueOf(w.Input) method := client.MethodByName(w.Config.Operation + "Request") for i := 0; i < w.MaxAttempts; i++ { res := method.Call([]reflect.Value{in}) req := res[0].Interface().(*request.Request) req.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Waiter")) if err := req.Send(); err != nil { return err } for _, a := range w.Acceptors { result := false switch a.Matcher { case "pathAll": if vals, _ := awsutil.ValuesAtPath(req.Data, a.Argument); req.Error == nil && vals != nil { result = true for _, val := range vals { if !reflect.DeepEqual(val, a.Expected) { result = false break } } } case "pathAny": if vals, _ := awsutil.ValuesAtPath(req.Data, a.Argument); req.Error == nil && vals != nil { for _, val := range vals { if reflect.DeepEqual(val, a.Expected) { result = true break } } } case "status": s := a.Expected.(int) result = s == req.HTTPResponse.StatusCode } if result { switch a.State { case "success": return nil // waiter completed case "failure": return req.Error // waiter failed case "retry": // do nothing, just retry } break } } time.Sleep(time.Second * time.Duration(w.Delay)) } return awserr.New("ResourceNotReady", fmt.Sprintf("exceeded %d wait attempts", w.MaxAttempts), nil) }
func TestValueAtPathFailure(t *testing.T) { assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, "C.x")) assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, ".x")) assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "X.Y.Z")) assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "A[100].C")) assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "A[3].C")) assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "B.B.C.Z")) assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, "z[-1].C")) assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(nil, "A.B.C")) assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(Struct{}, "A")) }
func TestValueAtPathSuccess(t *testing.T) { assert.Equal(t, []interface{}{"initial"}, awsutil.ValuesAtPath(data, "C")) assert.Equal(t, []interface{}{"value1"}, awsutil.ValuesAtPath(data, "A[0].C")) assert.Equal(t, []interface{}{"value2"}, awsutil.ValuesAtPath(data, "A[1].C")) assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtPath(data, "A[2].C")) assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtAnyPath(data, "a[2].c")) assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtPath(data, "A[-1].C")) assert.Equal(t, []interface{}{"value1", "value2", "value3"}, awsutil.ValuesAtPath(data, "A[].C")) assert.Equal(t, []interface{}{"terminal"}, awsutil.ValuesAtPath(data, "B . B . C")) assert.Equal(t, []interface{}{"terminal", "terminal2"}, awsutil.ValuesAtPath(data, "B.*.C")) assert.Equal(t, []interface{}{"initial"}, awsutil.ValuesAtPath(data, "A.D.X || C")) }
func getAllMetrics(cwData *datasourceInfo) (cloudwatch.ListMetricsOutput, error) { creds, err := getCredentials(cwData) if err != nil { return cloudwatch.ListMetricsOutput{}, err } cfg := &aws.Config{ Region: aws.String(cwData.Region), Credentials: creds, } svc := cloudwatch.New(session.New(cfg), cfg) params := &cloudwatch.ListMetricsInput{ Namespace: aws.String(cwData.Namespace), } var resp cloudwatch.ListMetricsOutput err = svc.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { metrics.M_Aws_CloudWatch_ListMetrics.Inc(1) metrics, _ := awsutil.ValuesAtPath(page, "Metrics") for _, metric := range metrics { resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric)) } return !lastPage }) if err != nil { return resp, err } return resp, nil }
func TestValueAtPathSuccess(t *testing.T) { var testCases = []struct { expect []interface{} data interface{} path string }{ {[]interface{}{"initial"}, data, "C"}, {[]interface{}{"value1"}, data, "A[0].C"}, {[]interface{}{"value2"}, data, "A[1].C"}, {[]interface{}{"value3"}, data, "A[2].C"}, {[]interface{}{"value3"}, data, "a[2].c"}, {[]interface{}{"value3"}, data, "A[-1].C"}, {[]interface{}{"value1", "value2", "value3"}, data, "A[].C"}, {[]interface{}{"terminal"}, data, "B . B . C"}, {[]interface{}{"initial"}, data, "A.D.X || C"}, {[]interface{}{"initial"}, data, "A[0].B || C"}, {[]interface{}{ Struct{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}}, Struct{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}}, }, data2, "A"}, } for i, c := range testCases { v, err := awsutil.ValuesAtPath(c.data, c.path) assert.NoError(t, err, "case %d, expected no error, %s", i, c.path) assert.Equal(t, c.expect, v, "case %d, %s", i, c.path) } }
func TestValueAtPathFailure(t *testing.T) { var testCases = []struct { expect []interface{} errContains string data interface{} path string }{ {nil, "", data, "C.x"}, {nil, "SyntaxError: Invalid token: tDot", data, ".x"}, {nil, "", data, "X.Y.Z"}, {nil, "", data, "A[100].C"}, {nil, "", data, "A[3].C"}, {nil, "", data, "B.B.C.Z"}, {nil, "", data, "z[-1].C"}, {nil, "", nil, "A.B.C"}, {[]interface{}{}, "", Struct{}, "A"}, {nil, "", data, "A[0].B.C"}, {nil, "", data, "D"}, } for i, c := range testCases { v, err := awsutil.ValuesAtPath(c.data, c.path) if c.errContains != "" { assert.Contains(t, err.Error(), c.errContains, "case %d, expected error, %s", i, c.path) continue } else { assert.NoError(t, err, "case %d, expected no error, %s", i, c.path) } assert.Equal(t, c.expect, v, "case %d, %s", i, c.path) } }
func getAllMetrics(region string, namespace string, database string) (cloudwatch.ListMetricsOutput, error) { cfg := &aws.Config{ Region: aws.String(region), Credentials: getCredentials(database), } svc := cloudwatch.New(session.New(cfg), cfg) params := &cloudwatch.ListMetricsInput{ Namespace: aws.String(namespace), } var resp cloudwatch.ListMetricsOutput err := svc.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { metrics, _ := awsutil.ValuesAtPath(page, "Metrics") for _, metric := range metrics { resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric)) } return !lastPage }) if err != nil { return resp, err } return resp, nil }
func handleListMetrics(req *cwRequest, c *middleware.Context) { cfg := getAwsConfig(req) svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { Parameters struct { Namespace string `json:"namespace"` MetricName string `json:"metricName"` Dimensions []*cloudwatch.DimensionFilter `json:"dimensions"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) params := &cloudwatch.ListMetricsInput{ Namespace: aws.String(reqParam.Parameters.Namespace), MetricName: aws.String(reqParam.Parameters.MetricName), Dimensions: reqParam.Parameters.Dimensions, } var resp cloudwatch.ListMetricsOutput err := svc.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { metrics, _ := awsutil.ValuesAtPath(page, "Metrics") for _, metric := range metrics { resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric)) } return !lastPage }) if err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } c.JSON(200, resp) }
func validateSSERequiresSSL(r *request.Request) { if r.HTTPRequest.URL.Scheme != "https" { p := awsutil.ValuesAtPath(r.Params, "SSECustomerKey||CopySourceSSECustomerKey") if len(p) > 0 { r.Error = errSSERequiresSSL } } }
func TestNoPopulateLocationConstraintIfClassic(t *testing.T) { s := s3.New(&aws.Config{Region: aws.String("us-east-1")}) req, _ := s.CreateBucketRequest(&s3.CreateBucketInput{ Bucket: aws.String("bucket"), }) err := req.Build() assert.NoError(t, err) assert.Equal(t, 0, len(awsutil.ValuesAtPath(req.Params, "CreateBucketConfiguration.LocationConstraint"))) }
func TestNoPopulateLocationConstraintIfProvided(t *testing.T) { s := s3.New(nil) req, _ := s.CreateBucketRequest(&s3.CreateBucketInput{ Bucket: aws.String("bucket"), CreateBucketConfiguration: &s3.CreateBucketConfiguration{}, }) err := req.Build() assert.NoError(t, err) assert.Equal(t, 0, len(awsutil.ValuesAtPath(req.Params, "CreateBucketConfiguration.LocationConstraint"))) }
func TestPopulateLocationConstraint(t *testing.T) { s := s3.New(nil) in := &s3.CreateBucketInput{ Bucket: aws.String("bucket"), } req, _ := s.CreateBucketRequest(in) err := req.Build() assert.NoError(t, err) assert.Equal(t, "mock-region", awsutil.ValuesAtPath(req.Params, "CreateBucketConfiguration.LocationConstraint")[0]) assert.Nil(t, in.CreateBucketConfiguration) // don't modify original params }
func updateHostWithBucket(r *request.Request) { b := awsutil.ValuesAtPath(r.Params, "Bucket") if len(b) == 0 { return } if bucket := b[0].(string); bucket != "" && hostStyleBucketName(r, bucket) { r.HTTPRequest.URL.Host = bucket + "." + r.HTTPRequest.URL.Host r.HTTPRequest.URL.Path = strings.Replace(r.HTTPRequest.URL.Path, "/{Bucket}", "", -1) if r.HTTPRequest.URL.Path == "" { r.HTTPRequest.URL.Path = "/" } } }
// Attempts to retrieve the bucket name from the request input parameters. // If no bucket is found, or the field is empty "", false will be returned. func bucketNameFromReqParams(params interface{}) (string, bool) { b, _ := awsutil.ValuesAtPath(params, "Bucket") if len(b) == 0 { return "", false } if bucket, ok := b[0].(*string); ok { if bucketStr := aws.StringValue(bucket); bucketStr != "" { return bucketStr, true } } return "", false }
func TestFillAccountIDWithNilStruct(t *testing.T) { req, _ := svc.ListVaultsRequest(nil) err := req.Build() assert.NoError(t, err) empty := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" // Sets Account ID v := awsutil.ValuesAtPath(req.Params, "AccountID") assert.Equal(t, "-", v[0]) // Does not set tree hash assert.Equal(t, empty, req.HTTPRequest.Header.Get("x-amz-content-sha256")) assert.Equal(t, "", req.HTTPRequest.Header.Get("x-amz-sha256-tree-hash")) }
func val(i interface{}, s string) interface{} { v, err := awsutil.ValuesAtPath(i, s) if err != nil || len(v) == 0 { return nil } if _, ok := v[0].(io.Reader); ok { return v[0] } if rv := reflect.ValueOf(v[0]); rv.Kind() == reflect.Ptr { return rv.Elem().Interface() } return v[0] }
func handleDescribeInstances(req *cwRequest, c *middleware.Context) { sess := session.New() creds := credentials.NewChainCredentials( []credentials.Provider{ &credentials.EnvProvider{}, &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, }) cfg := &aws.Config{ Region: aws.String(req.Region), Credentials: creds, } svc := ec2.New(session.New(cfg), cfg) reqParam := &struct { Parameters struct { Filters []*ec2.Filter `json:"filters"` InstanceIds []*string `json:"instanceIds"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) params := &ec2.DescribeInstancesInput{} if len(reqParam.Parameters.Filters) > 0 { params.Filters = reqParam.Parameters.Filters } if len(reqParam.Parameters.InstanceIds) > 0 { params.InstanceIds = reqParam.Parameters.InstanceIds } var resp ec2.DescribeInstancesOutput err := svc.DescribeInstancesPages(params, func(page *ec2.DescribeInstancesOutput, lastPage bool) bool { reservations, _ := awsutil.ValuesAtPath(page, "Reservations") for _, reservation := range reservations { resp.Reservations = append(resp.Reservations, reservation.(*ec2.Reservation)) } return !lastPage }) if err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } c.JSON(200, resp) }
func (r *hostsList) Run() error { // Create an EC2 service object in the "eu-west-1" region // Note that you can also configure your region globally by // exporting the AWS_REGION environment variable svc := ec2.New(session.New(), &aws.Config{Region: aws.String("eu-west-1")}) // we are only concerned with running instances filterChain := &ec2.DescribeInstancesInput{ Filters: []*ec2.Filter{ &ec2.Filter{ Name: aws.String("instance-state-name"), Values: aws.StringSlice([]string{"running"}), }, //&ec2.Filter{ // Name: aws.String("tag:Env"), // Values: aws.StringSlice([]string{"staging"}), //}, }, } // filter by environment //Query string `cli:"arg"` // Call the DescribeInstances Operation resp, err := svc.DescribeInstances(filterChain) if err != nil { panic(err) } // id launch_time ami name ip type revision role t := gocli.NewTable() t.Header("id", "launch_time", "ami", "name", "ip", "public_ip", "type", "revision", "role") instances, _ := awsutil.ValuesAtPath(resp, "Reservations[].Instances[]") for _, instance := range instances { h := instance.(*ec2.Instance) tags := aggregateTags(h.Tags) // TODO - calculate role from tags role := gocli.Red("NONE") t.Add(h.InstanceId, h.LaunchTime.Format("2006-01-02T15:04"), h.ImageId, tags["Name"], h.PrivateIpAddress, h.PublicIpAddress, h.InstanceType, "aabbcc", role) } t.SortBy = 1 sort.Sort(sort.Reverse(t)) fmt.Println(t) return nil }
func handleListMetrics(req *cwRequest, c *middleware.Context) { sess := session.New() creds := credentials.NewChainCredentials( []credentials.Provider{ &credentials.EnvProvider{}, &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}, }) cfg := &aws.Config{ Region: aws.String(req.Region), Credentials: creds, } svc := cloudwatch.New(session.New(cfg), cfg) reqParam := &struct { Parameters struct { Namespace string `json:"namespace"` MetricName string `json:"metricName"` Dimensions []*cloudwatch.DimensionFilter `json:"dimensions"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) params := &cloudwatch.ListMetricsInput{ Namespace: aws.String(reqParam.Parameters.Namespace), MetricName: aws.String(reqParam.Parameters.MetricName), Dimensions: reqParam.Parameters.Dimensions, } var resp cloudwatch.ListMetricsOutput err := svc.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { metrics, _ := awsutil.ValuesAtPath(page, "Metrics") for _, metric := range metrics { resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric)) } return !lastPage }) if err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } c.JSON(200, resp) }
func TestCustomizations(t *testing.T) { req, _ := svc.UploadArchiveRequest(&glacier.UploadArchiveInput{ VaultName: aws.String("vault"), Body: payloadBuf, }) err := req.Build() assert.NoError(t, err) // Sets API version assert.Equal(t, req.Service.APIVersion, req.HTTPRequest.Header.Get("x-amz-glacier-version")) // Sets Account ID v := awsutil.ValuesAtPath(req.Params, "AccountID") assert.Equal(t, "-", v[0]) // Computes checksums linear := "68aff0c5a91aa0491752bfb96e3fef33eb74953804f6a2f7b708d5bcefa8ff6b" tree := "154e26c78fd74d0c2c9b3cc4644191619dc4f2cd539ae2a74d5fd07957a3ee6a" assert.Equal(t, linear, req.HTTPRequest.Header.Get("x-amz-content-sha256")) assert.Equal(t, tree, req.HTTPRequest.Header.Get("x-amz-sha256-tree-hash")) }
func handleDescribeInstances(req *cwRequest, c *middleware.Context) { cfg := &aws.Config{ Region: aws.String(req.Region), Credentials: getCredentials(req.DataSource.Database), } svc := ec2.New(session.New(cfg), cfg) reqParam := &struct { Parameters struct { Filters []*ec2.Filter `json:"filters"` InstanceIds []*string `json:"instanceIds"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) params := &ec2.DescribeInstancesInput{} if len(reqParam.Parameters.Filters) > 0 { params.Filters = reqParam.Parameters.Filters } if len(reqParam.Parameters.InstanceIds) > 0 { params.InstanceIds = reqParam.Parameters.InstanceIds } var resp ec2.DescribeInstancesOutput err := svc.DescribeInstancesPages(params, func(page *ec2.DescribeInstancesOutput, lastPage bool) bool { reservations, _ := awsutil.ValuesAtPath(page, "Reservations") for _, reservation := range reservations { resp.Reservations = append(resp.Reservations, reservation.(*ec2.Reservation)) } return !lastPage }) if err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } c.JSON(200, resp) }
// Get a list of running EC2 instances func LoadInstances() ([]*ec2.Instance, error) { svc := ec2.New(session.New(), &aws.Config{Region: aws.String("eu-west-1")}) // we are only concerned with running instances filterChain := &ec2.DescribeInstancesInput{ Filters: []*ec2.Filter{ &ec2.Filter{ Name: aws.String("instance-state-name"), Values: aws.StringSlice([]string{"running"}), }, }, } // Call the DescribeInstances Operation resp, err := svc.DescribeInstances(filterChain) instances, _ := awsutil.ValuesAtPath(resp, "Reservations[].Instances[]") ret := make([]*ec2.Instance, len(instances)) for i := range instances { ret[i] = instances[i].(*ec2.Instance) } return ret, err }
func val(i interface{}, s string) interface{} { return awsutil.ValuesAtPath(i, s)[0] }
// Wait waits for an operation to complete, expire max attempts, or fail. Error // is returned if the operation fails. func (w *Waiter) Wait() error { client := reflect.ValueOf(w.Client) in := reflect.ValueOf(w.Input) method := client.MethodByName(w.Config.Operation + "Request") for i := 0; i < w.MaxAttempts; i++ { res := method.Call([]reflect.Value{in}) req := res[0].Interface().(*request.Request) req.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Waiter")) err := req.Send() for _, a := range w.Acceptors { if err != nil && a.Matcher != "error" { // Only matcher error is valid if there is a request error continue } result := false var vals []interface{} switch a.Matcher { case "pathAll", "path": // Require all matches to be equal for result to match vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument) result = true for _, val := range vals { if !awsutil.DeepEqual(val, a.Expected) { result = false break } } case "pathAny": // Only a single match needs to equal for the result to match vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument) for _, val := range vals { if awsutil.DeepEqual(val, a.Expected) { result = true break } } case "status": s := a.Expected.(int) result = s == req.HTTPResponse.StatusCode case "error": if aerr, ok := err.(awserr.Error); ok { result = aerr.Code() == a.Expected.(string) } case "pathList": // ignored matcher default: logf(client, "WARNING: Waiter for %s encountered unexpected matcher: %s", w.Config.Operation, a.Matcher) } if !result { // If there was no matching result found there is nothing more to do // for this response, retry the request. continue } switch a.State { case "success": // waiter completed return nil case "failure": // Waiter failure state triggered return awserr.New("ResourceNotReady", fmt.Sprintf("failed waiting for successful resource state"), err) case "retry": // clear the error and retry the operation err = nil default: logf(client, "WARNING: Waiter for %s encountered unexpected state: %s", w.Config.Operation, a.State) } } if err != nil { return err } time.Sleep(time.Second * time.Duration(w.Delay)) } return awserr.New("ResourceNotReady", fmt.Sprintf("exceeded %d wait attempts", w.MaxAttempts), nil) }
func init() { logLevel := Session.Config.LogLevel if os.Getenv("DEBUG") != "" { logLevel = aws.LogLevel(aws.LogDebug) } if os.Getenv("DEBUG_SIGNING") != "" { logLevel = aws.LogLevel(aws.LogDebugWithSigning) } if os.Getenv("DEBUG_BODY") != "" { logLevel = aws.LogLevel(aws.LogDebugWithHTTPBody) } Session.Config.LogLevel = logLevel When(`^I call the "(.+?)" API$`, func(op string) { call(op, nil, false) }) When(`^I call the "(.+?)" API with:$`, func(op string, args [][]string) { call(op, args, false) }) Then(`^the value at "(.+?)" should be a list$`, func(member string) { vals, _ := awsutil.ValuesAtPath(World["response"], member) assert.NotNil(T, vals) }) Then(`^the response should contain a "(.+?)"$`, func(member string) { vals, _ := awsutil.ValuesAtPath(World["response"], member) assert.NotEmpty(T, vals) }) When(`^I attempt to call the "(.+?)" API with:$`, func(op string, args [][]string) { call(op, args, true) }) Then(`^I expect the response error code to be "(.+?)"$`, func(code string) { err, ok := World["error"].(awserr.Error) assert.True(T, ok, "no error returned") if ok { assert.Equal(T, code, err.Code(), "Error: %v", err) } }) And(`^I expect the response error message to include:$`, func(data string) { err, ok := World["error"].(awserr.Error) assert.True(T, ok, "no error returned") if ok { assert.Contains(T, err.Message(), data) } }) And(`^I expect the response error message to include one of:$`, func(table [][]string) { err, ok := World["error"].(awserr.Error) assert.True(T, ok, "no error returned") if ok { found := false for _, row := range table { if strings.Contains(err.Message(), row[0]) { found = true break } } assert.True(T, found, fmt.Sprintf("no error messages matched: \"%s\"", err.Message())) } }) And(`^I expect the response error message not be empty$`, func() { err, ok := World["error"].(awserr.Error) assert.True(T, ok, "no error returned") assert.NotEmpty(T, err.Message()) }) When(`^I call the "(.+?)" API with JSON:$`, func(s1 string, data string) { callWithJSON(s1, data, false) }) When(`^I attempt to call the "(.+?)" API with JSON:$`, func(s1 string, data string) { callWithJSON(s1, data, true) }) Then(`^the error code should be "(.+?)"$`, func(s1 string) { err, ok := World["error"].(awserr.Error) assert.True(T, ok, "no error returned") assert.Equal(T, s1, err.Code()) }) And(`^the error message should contain:$`, func(data string) { err, ok := World["error"].(awserr.Error) assert.True(T, ok, "no error returned") assert.Contains(T, err.Error(), data) }) Then(`^the request should fail$`, func() { err, ok := World["error"].(awserr.Error) assert.True(T, ok, "no error returned") assert.Error(T, err) }) Then(`^the request should be successful$`, func() { err, ok := World["error"].(awserr.Error) assert.False(T, ok, "error returned") assert.NoError(T, err) }) }