garnaat / placebo

Make boto3 calls that look real but have no effect.
Apache License 2.0
394 stars 28 forks source link

Added test case for order of calls for playback (see issue #33) #37

Open vlcinsky opened 8 years ago

vlcinsky commented 8 years ago
modified:   tests/unit/test_canned.py
garnaat commented 8 years ago

Looks like you just have to specify a region when you create the Session object.

vlcinsky commented 8 years ago

I wonder, if Session shall always get region_name specified. Signature does not declare region_name as obligatory and in other cases it works well.

Anyway, I added region_name to creation of session in the test and it is still failing. The type of failure depends on environment, where it is tested. If it runs on Travis, it complains:

AttributeError: 'NoneType' object has no attribute 'get_frozen_credentials'

If I run it locally, it ignores the pill mode being playback and sends the request to real AWS service - then it fails on check for the value retrieved (which differs from what is in saved responses).

garnaat commented 8 years ago

You can't create a client without specifying a region somewhere. It can come from your config file, from an environment variable, you can specify it when creating the Session or when creating the client but a client needs to know which endpoint it is talking to.

vlcinsky commented 8 years ago

I will have to accept you are correct with region_name being required for creating a session.

Since I use mostly S3 services and since bucket names are using global (unique across all regions) scope, I was always expecting, that I shall get the bucket without taking care about region it resides at. Despite the fact, there is some logic in my requirement, there are practical consequences, that in many cases it could cause additional request to AWS which can cost something and which can be avoided, if region is known.

So thanks - from this issue I take away the fact, region_name is really required (from somewhere) for a session.

garnaat commented 8 years ago

Just to be clear, a region is not required to create a Session but it is required to create a client/resource.

The error that you are getting in the tests right now is because you are not configuring the session to use the fake credential file in the test directory.

If you look at this, you can see the Session is being created using the footer profile which is defined in the file tests/unit/cfg/aws_credentials. By configuring the Session object to use these fake credentials, we guarantee that boto will not go off looking for real credentials somewhere. But because you have not configured your Session in this way, the Session object is doing it's normal search to find credentials. When you run in on your local machine, it will find them in your config file. When it is run on CircleCI, it is unable to find any and the tests fail.

Does that make sense?

jamesdehart commented 7 years ago

@vlcinsky I'm trying to understand how to use placebo and I came across your PR.

This snip right here is calling boto before the placebo is able to replay the data. This makes a real API call. If the region is not provided when creating a session. Then boto will search for the aws config file or env vars to find it. See Configuring Credentials

    def test_client_pill_playback(self):
        self.session = boto3.Session(region_name=self.region_name)
        ec2_client = self.session.client('ec2')
        self.pill = placebo.attach(self.session, self.data_path)
        self.pill.playback()

        self.check_ec2_client_describe_addresses(ec2_client)

These two tests are not making a real API call but using the recorded data.

    def setUp(self):
        # ... Removed to reduce the message.
        self.region_name = 'foo'

    def test_pill_client_playback(self):
        self.session = boto3.Session(region_name=self.region_name)
        self.pill = placebo.attach(self.session, self.data_path)
        ec2_client = self.session.client('ec2')
        self.pill.playback()

        self.check_ec2_client_describe_addresses(ec2_client)

    def test_pill_playback_client(self):
        self.session = boto3.Session()
        self.pill = placebo.attach(self.session, self.data_path)
        self.pill.playback()
        ec2_client = self.session.client('ec2')

        self.check_ec2_client_describe_addresses(ec2_client)

Everything worked as expected. Note I have a ~/.aws/config file.

I hope this helps. Not sure if this PR is needed to stay open @garnaat ?