Repository: localstack/localstack

Issue:
bug: Responses contain mixed-case boolean values
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

I'm using [Localstack with the Rust SDK](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/localstack.html), and it is reporting an error parsing the `RunInstancesResponse` type:

```
Error: Error parsing XML: expected (boolean: `com.amazonaws.ec2#Boolean`)

Caused by:
    0: Error parsing XML: expected (boolean: `com.amazonaws.ec2#Boolean`)
    1: Error parsing XML: expected (boolean: `com.amazonaws.ec2#Boolean`)
```

The response contains this:

```
<ebsOptimized>False</ebsOptimized>
```

which does not conform to the API reference's description of [AttributeBooleanValue](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AttributeBooleanValue.html), which says that the valid values are `true` or `false`.

### Expected Behavior

The API should return boolean values in lowercase as specified by the Amazon API Reference.

### How are you starting LocalStack?

With a docker-compose file

### Steps To Reproduce

#### How are you starting localstack (e.g., `bin/localstack` command, arguments, or `docker-compose.yml`)

```yaml
version: "3.8"

services:
  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
    image: localstack/localstack
    network_mode: bridge
    ports:
      - "127.0.0.1:4510-4559:4510-4559"  # external service port range
      - "127.0.0.1:4566:4566"            # LocalStack Edge Proxy
    environment:
      - DEBUG=${DEBUG-}
      - DATA_DIR=${DATA_DIR-}
      - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-}
      - DOCKER_HOST=unix:///var/run/docker.sock
    volumes:
      - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
      - "${DOCKER_SOCK:-/var/run/docker.sock}:/var/run/docker.sock"
```

#### Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)

```rust
let ec2: aws_sdk_ec2::Client = ...;
let resp = ec2
    .run_instances()
    .image_id(image_id)
    .max_count(1)
    .min_count(1)
    .key_name(key_name)
    .security_group_ids(gid)
    .subnet_id(sid)
    .send()
    .await?;
```


### Environment

```markdown
- OS: Ubuntu 18.04 LTS
- LocalStack:

localstack_main | LocalStack version: 1.0.2.dev
localstack_main | LocalStack Docker container id: 73a491727a3c
localstack_main | LocalStack build date: 2022-07-20
localstack_main | LocalStack build git hash: e105e488
```
```


### Anything else?

_No response_


Discussion:
Welcome to LocalStack! Thanks for reporting your first issue and our team will be working towards fixing the issue for you or reach out for more background information. We recommend joining our [Slack Community](https://localstack.cloud/contact/) for real-time help and drop a message to LocalStack Pro Support if you are a Pro user! If you are willing to contribute towards fixing this issue, please have a look at our [contributing guidelines](https://github.com/localstack/.github/blob/main/CONTRIBUTING.md) and our [developer guide](https://docs.localstack.cloud/developer-guide/).

Resolving patch:
diff --git a/localstack/utils/aws/aws_responses.py b/localstack/utils/aws/aws_responses.py
--- a/localstack/utils/aws/aws_responses.py
+++ b/localstack/utils/aws/aws_responses.py
@@ -103,8 +103,10 @@ def _to_xml(parent_el: ET.Element, data_rest) -> None:
                 _to_xml(curr_el, value)
         elif isinstance(data_rest, str):
             parent_el.text = data_rest
+        elif isinstance(data_rest, bool):
+            parent_el.text = str(data_rest).lower()
         elif any(
-            isinstance(data_rest, i) for i in [bool, str, int, float]
+            isinstance(data_rest, i) for i in [int, float]
         ):  # limit types for text serialization
             parent_el.text = str(data_rest)
         else:


Test patch:
diff --git a/tests/unit/utils/aws/test_aws_responses.py b/tests/unit/utils/aws/test_aws_responses.py
--- a/tests/unit/utils/aws/test_aws_responses.py
+++ b/tests/unit/utils/aws/test_aws_responses.py
@@ -30,7 +30,7 @@
     [
         (
             result_raw,
-            "<member><ResourceChange><Replacement>False</Replacement><Scope><member>Tags</member></Scope></ResourceChange><Type>Resource</Type></member>",
+            "<member><ResourceChange><Replacement>false</Replacement><Scope><member>Tags</member></Scope></ResourceChange><Type>Resource</Type></member>",
         ),
         (result_raw_none_element, "<b />"),
         (result_raw_empty_list, "<b />"),