Repository: getmoto/moto

Issue:
AssociatePublicIpAddress = False on primary network interface is ignored
When creating an ec2 instance and a primary network interface with `"AssociatePublicIpAddress": False`, an instance is created with a public IP address.

I am expecting no public IP address to be created.

Example request:

```
kwargs = {
        "ImageId": ami,
        "MaxCount": 1,
        "MinCount": 1,
        "KeyName": "test-key",
        "InstanceType": "t2.medium",
        "EbsOptimized": False,
        "NetworkInterfaces": [
            {
                "DeviceIndex": 0,
                "Description": "Primary network interface",
                "DeleteOnTermination": True,
                "SubnetId": "subnet-317243a9",
                "Ipv6AddressCount": 0,
                "Groups": "default",
                "AssociatePublicIpAddress": False,
            }
        ]
    }
```

I'm using moto 1.3.14


Discussion:

Resolving patch:
diff --git a/moto/ec2/models.py b/moto/ec2/models.py
--- a/moto/ec2/models.py
+++ b/moto/ec2/models.py
@@ -410,7 +410,10 @@ def start(self):
         self.check_auto_public_ip()
 
     def check_auto_public_ip(self):
-        if self.public_ip_auto_assign:
+        if (
+            self.public_ip_auto_assign
+            and str(self.public_ip_auto_assign).lower() == "true"
+        ):
             self.public_ip = random_public_ip()
 
     @property


Test patch:
diff --git a/tests/test_ec2/test_instances.py b/tests/test_ec2/test_instances.py
--- a/tests/test_ec2/test_instances.py
+++ b/tests/test_ec2/test_instances.py
@@ -3044,6 +3044,58 @@ def test_create_instance_with_launch_template_id_produces_no_warning(
     assert len(captured_warnings) == 0
 
 
+@mock_ec2
+def test_run_instance_and_associate_public_ip():
+    ec2 = boto3.resource("ec2", "us-west-1")
+    vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
+    subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
+
+    # Do not pass AssociatePublicIpAddress-argument
+    instance = ec2.create_instances(
+        ImageId=EXAMPLE_AMI_ID,
+        MinCount=1,
+        MaxCount=1,
+        NetworkInterfaces=[{"DeviceIndex": 0}],
+        SubnetId=subnet.id,
+    )[0]
+    interfaces = instance.network_interfaces_attribute
+    addresses = interfaces[0]["PrivateIpAddresses"][0]
+    addresses.should.have.key("Primary").equal(True)
+    addresses.should.have.key("PrivateIpAddress")
+    addresses.shouldnt.have.key("Association")
+
+    # Pass AssociatePublicIpAddress=False
+    instance = ec2.create_instances(
+        ImageId=EXAMPLE_AMI_ID,
+        MinCount=1,
+        MaxCount=1,
+        NetworkInterfaces=[{"DeviceIndex": 0, "AssociatePublicIpAddress": False}],
+        SubnetId=subnet.id,
+    )[0]
+    interfaces = instance.network_interfaces_attribute
+    addresses = interfaces[0]["PrivateIpAddresses"][0]
+    addresses.should.have.key("Primary").equal(True)
+    addresses.should.have.key("PrivateIpAddress")
+    addresses.shouldnt.have.key("Association")
+
+    # Pass AssociatePublicIpAddress=True
+    instance = ec2.create_instances(
+        ImageId=EXAMPLE_AMI_ID,
+        MinCount=1,
+        MaxCount=1,
+        NetworkInterfaces=[{"DeviceIndex": 0, "AssociatePublicIpAddress": True}],
+        SubnetId=subnet.id,
+    )[0]
+    interfaces = instance.network_interfaces_attribute
+    addresses = interfaces[0]["PrivateIpAddresses"][0]
+    addresses.should.have.key("Primary").equal(True)
+    addresses.should.have.key("PrivateIpAddress")
+    addresses.should.have.key("Association")
+    # Only now should we have a PublicIp
+    addresses["Association"].should.have.key("IpOwnerId").equal(ACCOUNT_ID)
+    addresses["Association"].should.have.key("PublicIp")
+
+
 def retrieve_all_reservations(client, filters=[]):
     resp = client.describe_instances(Filters=filters)
     all_reservations = resp["Reservations"]