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

Add profile_name option to sessions #69

Closed
wants to merge 1 commit into from
Closed

Conversation

danielgtaylor
Copy link
Member

This change makes it possible to create a session using a profile name, which
was previously only possible via an environment variable. It allows you to
create clients and resources from any number of sessions using any number of
profiles.

Given that we have the following ~/.aws/credentials:

[default]
aws_access_key_id = DEFAULT
aws_secret_access_key = SECRET1

[dev]
aws_access_key_id = DEV
aws_secret_access_key = SECRET2

[prod]
aws_access_key_id = PROD
aws_secret_access_key = SECRET3

You can do the following:

import boto3.session

dev = boto3.session.Session(profile_name='dev')
prod = boto3.session.Session(profile_name='prod')

for session in [dev, prod]:
    print('Profile: ' + session.profile)
    s3 = session.resource('s3')
    for bucket in s3.buckets.all():
        print(bucket.name)
    print('')

It is also possible to setup the default session with a profile:

import boto3

boto3.setup_default_session(profile_name='dev')

s3 = boto3.resource('s3')

And of course you can still use the environment variable:

$ BOTO_DEFAULT_PROFILE=dev ipython
>>> import boto3
>>> s3dev = boto3.resource('s3')

Once a session is created, the profile is immutable. The profile_name
property is provided for convenience and just surfaces the underlying
Botocore session's profile property.

Why not provide a profile name to the client and resource methods?
Currently there is no easy way to clone a session, and the behavior of
creating a new blank session (from one which may have customizations)
leads to possibly unintended side-effects like clients without the
proper event handlers registered. This would be an additive change
should we want to revisit in the future. At this point, the change
in this commit provides a way for Boto 3 users to use multiple profiles
without resorting to creating their own Botocore sessions.

I'm definitely open to suggestions and counter-arguments.

cc @jamesls @kyleknap

This change makes it possible to create a session using a profile name, which
was previously only possible via an environment variable. It allows you to
create clients and resources from any number of sessions using any number of
profiles.

Given that we have the following `~/.aws/credentials`:

```ini
[default]
aws_access_key_id = DEFAULT
aws_secret_access_key = SECRET1

[dev]
aws_access_key_id = DEV
aws_secret_access_key = SECRET2

[prod]
aws_access_key_id = PROD
aws_secret_access_key = SECRET3
```

You can do the following:

```python
import boto3.session

dev = boto3.session.Session(profile_name='dev')
prod = boto3.session.Session(profile_name='prod')

s3dev = dev.resource('s3')
s3prod = prod.resource('s3')

for resource in [s3dev, s3prod]:
    print('Profile: ' + resource.profile)
    for bucket in resource.buckets.all():
        print(bucket.name)
    print('')
```

It is also possible to setup the default session with a profile:

```python
import boto3

boto3.setup_default_session(profile_name='dev')

s3 = boto3.resource('s3')
```

And of course you can still use the environment variable:

```bash
$ BOTO_DEFAULT_PROFILE=dev ipython
>>> import boto3
>>> s3dev = boto3.resource('s3')
```

Once a session is created, the profile is immutable. The `profile_name`
property is provided for convenience and just surfaces the underlying
Botocore session's profile property.

Why not provide a profile name to the `client` and `resource` methods?
Currently there is no easy way to clone a session, and the behavior of
creating a new blank session (from one which may have customizations)
leads to possibly unintended side-effects like clients without the
proper event handlers registered. This would be an additive change
should we want to revisit in the future. At this point, the change
in this commit provides a way for Boto 3 users to use multiple profiles
without resorting to creating their own Botocore sessions.

I'm definitely open to suggestions and counter-arguments.
"""
The **read-only** profile name.
"""
return self._session.profile or 'default'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would strongly prefer that this always return a string, but it could be either 'default' or a blank string. It makes code like this simpler:

if session.profile.startswith('prod'):
    # Do something here!
    pass

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is probably ok at this layer. I believe the reason it's like that in botocore is because parts of the code need to distinguish between "was explicitly set to default by the user" and "try the default profile if one hasn't been set". The former case is an error, the latter case just means move on to the next credential provider.

@danielgtaylor danielgtaylor added the enhancement This issue requests an improvement to a current feature. label Feb 27, 2015
@danielgtaylor danielgtaylor self-assigned this Feb 27, 2015
@danielgtaylor
Copy link
Member Author

This is one possible implementation of #21.

@jamesls
Copy link
Member

jamesls commented Feb 27, 2015

I think this seems reasonable. Looks good to me, :shipit:

@kyleknap
Copy link
Contributor

Looks good 🚢

@danielgtaylor
Copy link
Member Author

Merged in 8da893b

@danielgtaylor danielgtaylor deleted the session-profile branch February 27, 2015 21:36
@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 2a10ea6 on session-profile into * on develop*.

@ream88
Copy link

ream88 commented Feb 3, 2016

For everybody coming from Google: it is now called AWS_PROFILE.

$ AWS_PROFILE=dev ipython
>>> import boto3
>>> s3dev = boto3.resource('s3')

@quiver
Copy link
Contributor

quiver commented Mar 4, 2016

kudos go to @Haihappen

@GBR-613
Copy link

GBR-613 commented Feb 2, 2020

It does not work for me now (Boto3 v1.11.9, Python v3.8.1), at least with S3

The profile I specify is listed in boto3.Session().available_profiles
AWS CLI does work with the profile.
Who could verify this functionality is not simply broken in the last versions?
Thanks in advance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement This issue requests an improvement to a current feature.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants