Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CreateBucket fails on non-aws endpoint due to non implemented feature #3603

Closed
tlawrence opened this issue Mar 2, 2018 · 16 comments · Fixed by #5842
Closed

CreateBucket fails on non-aws endpoint due to non implemented feature #3603

tlawrence opened this issue Mar 2, 2018 · 16 comments · Fixed by #5842
Labels
enhancement Requests to existing resources that expand the functionality or scope. service/s3 Issues and PRs that pertain to the s3 service.
Milestone

Comments

@tlawrence
Copy link

Terraform Version

Run terraform -v to show the version. If you are not running the latest version of Terraform, please upgrade because your issue may have already been fixed.

Terraform version: 0.11.3

Affected Resource(s)

Please list the resources as a list, for example:

  • aws_s3_bucket

Terraform template:

https://gist.github.com/tlawrence/9ce8f48af687630ff44029369e733313

Debug Output

Please provider a link to a GitHub Gist containing the complete debug output: https://www.terraform.io/docs/internals/debugging.html. Please do NOT paste the debug output in the issue; just paste a link to the Gist.

Panic Output

If Terraform produced a panic, please provide a link to a GitHub Gist containing the output of the crash.log.

Expected Behavior

Bucket should create

Actual Behavior

GetBucketWebsite returns 501 "NotImplemented" error. AWS-SDK retries 10 times then fails.
501 should be handled gracefully

Steps to Reproduce

  1. terraform apply

Important Factoids

Object storage platform is EMC ECS

tried to update the code in aws/resource_aws_s3_bucket.go to catch the error but think it may need catching in the SDK first?

@bflad
Copy link
Contributor

bflad commented Mar 2, 2018

You're likely correct that we'll want this handled upstream in the SDK. Have you opened a bug report with https://github.com/aws/aws-sdk-go/?

@bflad
Copy link
Contributor

bflad commented Mar 2, 2018

Sorry I should clarify. 😅

The retrying of the SDK on 501 NotImplemented, while we might be able to override some of the behavior, we would prefer that the retries were turned off upstream in the SDK.

Within the aws_s3_bucket resource, we might be able to catch that specific error and instead of error'ing out, produce a WARN log message and keep going.

@bflad bflad added enhancement Requests to existing resources that expand the functionality or scope. service/s3 Issues and PRs that pertain to the s3 service. labels Mar 2, 2018
@tlawrence
Copy link
Author

tlawrence commented Mar 5, 2018 via email

@tlawrence tlawrence changed the title CreateBucket fails on non-awe endpoint due to non implemented feature CreateBucket fails on non-aws endpoint due to non implemented feature Mar 5, 2018
@bflad
Copy link
Contributor

bflad commented Mar 5, 2018

We might be able to do something like this in config.go after line 470 to override the SDK retries. Are you able to build and run a custom provider to see if this works in your environment to make it fail without retries?

	# Untested - not recommended for public usage
	client.s3conn.Handlers.Retry.PushBack(func(r *request.Request) {
		if isAWSErr(r.Error, "NotImplemented", "") {
			r.Retryable = aws.Bool(false)
		}
	})

@tlawrence
Copy link
Author

SDK isse: aws/aws-sdk-go#1819

@tlawrence
Copy link
Author

@bflad thanks, that did prevent the retries. However, I am still not successfuly catching the error.

I have put this into aws/resource_aws_s3_bucket.go

   // Read the website configuration
   wsResponse, err := retryOnAwsCode("NoSuchBucket", func() (interface{}, error) {
     return s3conn.GetBucketWebsite(&s3.GetBucketWebsiteInput{
       Bucket: aws.String(d.Id()),
     })
   })
   ws := wsResponse.(*s3.GetBucketWebsiteOutput)
 
   if err != nil {
     // An S3 Bucket might not have a website configuration set.
     if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() != "NotImplemented" {
       return err
     }
     log.Printf("[WARN] S3 bucket: %s, no website configuration could be found.", d.Id())
   }

but it isn't picked up for some reason..

@bflad
Copy link
Contributor

bflad commented Mar 5, 2018

Out of curiosity, what happens with something like this?

// Untested - not recommended for public usage
gbwi := &s3.GetBucketWebsiteInput{
  Bucket: aws.String(d.Id()),
}
var gbwo *s3.GetBucketWebsiteOutput
err := resource.Retry(1*time.Minute, func() *resource.RetryError {    
  var err error
  gbwo, err = s3conn.GetBucketWebsite(gbwi)
  if err != nil {
    if isAWSErr(err, s3.ErrCodeNoSuchBucket, "") {
      return resource.RetryableError(err)
    }
    return resource.NonRetryableError(err)
  }
  return nil
})
 
if err != nil {
  if !isAWSErr(err, "NotImplemented", "") {
    return err
  }
  log.Printf("[WARN] S3 bucket: %s, no website configuration could be found.", d.Id())
}

@tlawrence
Copy link
Author

this worked:

+   if err != nil {
+     // An S3 Bucket might not have a website configuration set. 
+     if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() != "NotImplemented" {
+       return err
+     }
+     return nil
+   }

@tlawrence
Copy link
Author

yours is tidier. I'll add that.

Sorry, I'm pretty new to Go code, its pretty obvious now I look at it.

Is the override in config.go still required do you think?
And in terms of a PR, is it ok to leave the override in there (maybe referencing this issue)?

@tlawrence
Copy link
Author

slight change,

need to return nil otherwise original error is persisted:

+   if err != nil {
+     if !isAWSErr(err, "NotImplemented", "") {
+       return err
+     }
+     log.Printf("[WARN] S3 bucket: %s, website configuration not supported by storage server.", d.Id())
+     return nil
+   }

@bflad
Copy link
Contributor

bflad commented Mar 5, 2018

Is the override in config.go still required do you think?

If you don't want the SDK retries in Terraform for now, yes. Its just wasting everyone's time (for any S3 API implementation, its extremely unlikely an API will become "implemented" soon after an initial call that fails). I think its a trivial fix for the upstream SDK as-is, but maybe we should wait until they reply on your ticket as they may say the vendor should implement the error differently.

You might want to ensure the acceptance testing passes for all your use cases as I imagine there might be other "problem" code expecting a fully implemented S3 API. (Note this will take awhile unless you pick specific acceptance tests) make testacc TEST=./aws TESTARGS='-run=TestAccAWSS3Bucket_'

@tlawrence
Copy link
Author

Thanks for your help @bflad. Do those acceptance tests run live tasks against the storage? What creds do they use?

@bflad
Copy link
Contributor

bflad commented Mar 5, 2018

Do those acceptance tests run live tasks against the storage?

Yes, the tests will create randomly named buckets, configure them, and destroy them to exercise the Terraform code fully against the API. The testing framework does not touch anything it did not create (unless you run a special make command).

What creds do they use?

It should be the same credentials as you're configuring the AWS provider normally if they are environment variables (e.g. I use export AWS_PROFILE=... in my case locally). The acceptance testing provider defaults to us-west-2 region for most testing so you will need to override via AWS_DEFAULT_REGION environment variable if the vendor connection requires something specific. Although now that I think about it, I'm sure your provider connection is probably very specific and might not work easily with the acceptance testing framework.

@tlawrence
Copy link
Author

What does the AWS_PROFILE file look like?

we have the following in the Terraform "provider" block:

endpoints {
    s3 = "https://mystorageurl.com"
  }

The Creds and Region are read normally from the env vars.

@bflad
Copy link
Contributor

bflad commented Mar 5, 2018

Configuration profiles are documented here: https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html

The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables work fine too, I just use AWS_PROFILE instead of both of those.

I do not think there is a "standard" environment variable for overriding AWS endpoint URLs (or S3's) though. It may be supported in named profile configurations, but I have never tested that myself. AWS doesn't look like it supports that in the AWS CLI yet: aws/aws-cli#1270. If AWS does have endpoint override support via env var/profile, and its not supported in Terraform, we can add support for it.

@ghost
Copy link

ghost commented Apr 3, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@ghost ghost locked and limited conversation to collaborators Apr 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement Requests to existing resources that expand the functionality or scope. service/s3 Issues and PRs that pertain to the s3 service.
Projects
None yet
2 participants