mintel / pytest-localstack

Pytest plugin for local AWS integration tests
MIT License
78 stars 18 forks source link

Feature request ... iam, sts #25

Closed rpattcorner closed 5 years ago

rpattcorner commented 5 years ago

Looks like exactly what I need for a multiaccount configuration service ... especially because of the session scope that lets me test across accounts. But need iam and sts mocking, which localstack covers. Any guidance on either ETA or what it takes to add another service/endpoint to pytest-localstack?

jtdoepke commented 5 years ago

It's usually just a matter of adding them to these two lists. I'll go take a look at adding any missing services.

rpattcorner commented 5 years ago

That would be incredible! Hitting a dead end with localstack alone because everything seems to happen in one virtual account. But pytest_localstack very nicely simulates multiple accounts, per your s3_sync example. However 99% of our app's calls are to IAM, and they don't seem to be hitting a real endpoint in the container (unlike, say, S3 tests which seem to work fine).

This result is what leads me to think iam might be present in the two lists but not implemented:

test setup failed
self = <pytest_localstack.session.LocalstackSession object at 0x04086FD0>
hostname = '127.0.0.1', services = ['iam'], region_name = None, use_ssl = False
kwargs = {}, service_name = 'iam'
... STUFF...
        elif isinstance(services, (list, tuple, set)):
            self.services = {}
            for service_name in services:
                try:
>                   port = constants.SERVICE_PORTS[service_name]
E                   KeyError: 'iam'

E:\Program Files (x86)\Python37-32\lib\site-packages\pytest_localstack\session.py:40: KeyError

There's some muttering about region not being defined too, but that seems to have an intelligent default.

The test code is pretty basic, but I'm new to this and one never knows ...

localstack_identity = pytest_localstack.session_fixture(services=["iam"])
localstack_target_1 = pytest_localstack.session_fixture(services=["iam"])

...

def test_user_create2(localstack_identity, yaml_data):
    id_client = localstack_identity.boto3.resource("iam")
    target_client=localstack_target_1.boto3.resource("iam")
    arp_template = {"Version": "2012-10-17",
                    "Statement": [{"Effect": "Allow", "Principal": {"AWS": []}, "Action": "sts:AssumeRole"}]}
    arps=json.dumps(arp_template)
    response=id_client.create_role(RoleName='role1',AssumeRolePolicyDocument=arps)
    response2=target_client.create_role(RoleName='role1',AssumeRolePolicyDocument=arps)
    list1=id_client.list_roles()
    list2=target_client.list_roles()
jtdoepke commented 5 years ago

I've made a new release with IAM, STS, and others. A slightly modified version of your test is working for me:

import json

import pytest_localstack

localstack_identity = pytest_localstack.session_fixture(services=["iam"])
localstack_target_1 = pytest_localstack.session_fixture(services=["iam"])

def test_user_create2(localstack_identity, localstack_target_1):
    id_client = localstack_identity.boto3.client("iam")
    target_client = localstack_target_1.boto3.client("iam")

    arp_template = {
        "Version": "2012-10-17",
        "Statement": [
            {"Effect": "Allow", "Principal": {"AWS": []}, "Action": "sts:AssumeRole"}
        ],
    }
    arps = json.dumps(arp_template)

    id_client.create_role(RoleName="role1", AssumeRolePolicyDocument=arps)
    response = id_client.list_roles()
    assert "Roles" in response
    assert len(response["Roles"]) == 1
    assert response["Roles"][0]["RoleName"] == "role1"

    target_client.create_role(RoleName="role2", AssumeRolePolicyDocument=arps)
    response = target_client.list_roles()
    assert "Roles" in response
    assert len(response["Roles"]) == 1
    assert response["Roles"][0]["RoleName"] == "role2"

Good luck with your testing!

rpattcorner commented 5 years ago

Many, many thanks! Looks really good, and will make a lot of difference in our project. So far, so good!