1
votes

I'm trying to create an s3 bucket in every region in AWS with boto3 in python but I'm failing to create a bucket in 4 regions (af-south-1, eu-south-1, ap-east-1 & me-south-1)

My python code:

def create_bucket(name, region):
    s3 = boto3.client('s3')
    s3.create_bucket(Bucket=name, CreateBucketConfiguration={'LocationConstraint': region})

and the exception I get:

botocore.exceptions.ClientError: An error occurred (InvalidLocationConstraint) when calling the CreateBucket operation: The specified location-constraint is not valid

I can create buckets in these regions from the aws website but it is not good for me, so I tried to do create it directly from the rest API without boto3.

url: bucket-name.s3.amazonaws.com

body:

<?xml version="1.0" encoding="UTF-8"?>
<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   <LocationConstraint>eu-south-1</LocationConstraint>
</CreateBucketConfiguration>

but the response was similar to the exception:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>InvalidLocationConstraint</Code>
    <Message>The specified location-constraint is not valid</Message>
    <LocationConstraint>eu-south-1</LocationConstraint>
    <RequestId>********</RequestId>
    <HostId>**************</HostId>
</Error>

Does anyone have an idea why I can do it manually from the site but not from python?

2
Do you use the regional S3 endpoints, or just the global legacy endpoint "s3.amazonaws.com"? For virtual hosting, the legacy endpoint only works for the old regions, not the new ones. Maybe it's the same for the REST API?Christian
You are right! is there any way to make boto3 use the new URL and not the old one?Sean Goldfarb

2 Answers

1
votes

The regions your code fails in are relativly new regions, where you need to opt-in first to use them, see here Managing AWS Regions

0
votes

Newer AWS regions only support regional endpoints. Thus, if creating buckets in one of those regions, a regional endpoint needs to be created.

Since I was creating buckets in multiple regions, I set the endpoint by creating a new instance of the client for each region. (This was in Node.js, but should still work with boto3)

client = boto3.client('s3', region_name='region')

See the same problem on Node.js here