0

I recently asked this question:

moto unit test EC2 - 'NoneType' object has no attribute 'id'

I now have at least found out about why this error occurs.

I call ec2.run_instances() with multiple parameters, like this:

ec2.run_instances(
        ImageId=IMAGE_ID,
        MinCount=count,
        MaxCount=count,
        InstanceType=INSTANCE_TYPE,
        KeyName=KEY_NAME,
        SecurityGroupIds=[SECURITY_GROUP_ID]
    )

When trying to mock this like shown in my other question, I get an error because it can't find the specified securityGroupId.

When I comment out the SecurityGrouoIds like so:

...
        InstanceType=INSTANCE_TYPE,
        KeyName=KEY_NAME,
        #SecurityGroupIds=[SECURITY_GROUP_ID]
    )
...

the moto test runs fine.

How can I add the securityGroup to the instance? I have tried to use the solution from this question, but it didn't work out for me.

Does anyone have an Idea about how to mock / add the securityGroup to the ec2 mock?

Thanks in advance

Edit:

The test itself looks like this:

 @mock_ec2
    def test_create_instances_with_decorator(self):
        instance_count = 1
        image_id = 'ami-0df635fd7dea02388'
        client = boto3.client('ec2', region_name='eu-central-1')
        client.create_security_group(Description="my-test-group",GroupName="launch-wizard-1")
        mngr = aws_manager()
        mngr.launchInstances(2)
        instances = client.describe_instances()['Reservations'][0]['Instances']
        print(instances)
        assert len(instances) == 2
        assert instances[0]['ImageId'] == image_id

And the code to be tested looks like this:

SECURITY_GROUP_ID = "sg-0dc0a634bc153adc8"
REGION_NAME = "eu-central-1"
INSTANCE_TYPE = "t2.micro"
class aws_manager:

    def __init__(self) -> None:
        self.ec2 = boto3.client('ec2', region_name=REGION_NAME)
        self.running_instances = []

    def launchInstances(self, count: int):

            instances = self.ec2.run_instances(
                ImageId=IMAGE_ID,
                MinCount=count,
                MaxCount=count,
                InstanceType=INSTANCE_TYPE,
                KeyName=KEY_NAME,
                SecurityGroupIds=[SECURITY_GROUP_ID]
            )["Instances"][0]



codedor
  • 73
  • 6
  • Where does `SECURITY_GROUP_ID` come from? The security group has to be created first (using ec2.create_security_group`), then it should work fine. If you are creating it first, can you post a small reproducible test case? – Bert Blommers Jul 03 '22 at 10:55
  • Hello @BertBlommers , `SECURITY_GROUP_ID` = `sg-0dc0a634bc153adc8` in my case. This is the id of the `securitygroup`, that I want to use for each EC2 instance that is being created `launchInstances(count)`, so this is a required parameter for me. I have set it up before online in the EC2 Management Console. I edited the question and added some code. – codedor Jul 03 '22 at 11:53
  • @codedor where in your code is that assignment? It is not in anything you have posted. – jordanm Jul 03 '22 at 19:58
  • Side note, for creating resources like ec2 instances, I highly recommend using an infrastructure as code system such as Cloudformation or Terraform. These system are declarative rather than imperative and they keep track of the resources they have created. – jordanm Jul 03 '22 at 20:01
  • @jordanm I now added the assignment. Yeah that would be an alternative but shouldn't this work what I am trying to do? – codedor Jul 03 '22 at 21:29
  • It depends on how you import it, but you would need to use something like [unittest.patch](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch). I would however recommend just changing your actual code so that security_upgrade_id is and instance variable of the aws_manager object. That will make it easy to override from tests. – jordanm Jul 04 '22 at 02:44

0 Answers0