Repository: getmoto/moto

Issue:
API Gateway missing defaults when creating REST API
By default when creating a new rest api in API Gateway there are certain parameters with default values that are added by AWS which are missing from moto such as:

- apiKeySource
- endpointConfiguration
- tags

For instance:
```
$ aws apigateway create-rest-api --name jrbeilke-test
{
    "id": "w1wumry1zj",
    "name": "jrbeilke-test",
    "createdDate": 1580323604,
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    }
}

$ aws apigateway get-rest-api --rest-api-id w1wumry1zj
{
    "id": "w1wumry1zj",
    "name": "jrbeilke-test",
    "createdDate": 1580323604,
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "tags": {}
}
```


Discussion:

Resolving patch:
diff --git a/moto/apigateway/models.py b/moto/apigateway/models.py
--- a/moto/apigateway/models.py
+++ b/moto/apigateway/models.py
@@ -394,12 +394,17 @@ def __init__(self, id, type, name, value):
 
 
 class RestAPI(BaseModel):
-    def __init__(self, id, region_name, name, description):
+    def __init__(self, id, region_name, name, description, **kwargs):
         self.id = id
         self.region_name = region_name
         self.name = name
         self.description = description
         self.create_date = int(time.time())
+        self.api_key_source = kwargs.get("api_key_source") or "HEADER"
+        self.endpoint_configuration = kwargs.get("endpoint_configuration") or {
+            "types": ["EDGE"]
+        }
+        self.tags = kwargs.get("tags") or {}
 
         self.deployments = {}
         self.stages = {}
@@ -416,6 +421,9 @@ def to_dict(self):
             "name": self.name,
             "description": self.description,
             "createdDate": int(time.time()),
+            "apiKeySource": self.api_key_source,
+            "endpointConfiguration": self.endpoint_configuration,
+            "tags": self.tags,
         }
 
     def add_child(self, path, parent_id=None):
@@ -529,9 +537,24 @@ def reset(self):
         self.__dict__ = {}
         self.__init__(region_name)
 
-    def create_rest_api(self, name, description):
+    def create_rest_api(
+        self,
+        name,
+        description,
+        api_key_source=None,
+        endpoint_configuration=None,
+        tags=None,
+    ):
         api_id = create_id()
-        rest_api = RestAPI(api_id, self.region_name, name, description)
+        rest_api = RestAPI(
+            api_id,
+            self.region_name,
+            name,
+            description,
+            api_key_source=api_key_source,
+            endpoint_configuration=endpoint_configuration,
+            tags=tags,
+        )
         self.apis[api_id] = rest_api
         return rest_api
 
diff --git a/moto/apigateway/responses.py b/moto/apigateway/responses.py
--- a/moto/apigateway/responses.py
+++ b/moto/apigateway/responses.py
@@ -12,6 +12,9 @@
     ApiKeyAlreadyExists,
 )
 
+API_KEY_SOURCES = ["AUTHORIZER", "HEADER"]
+ENDPOINT_CONFIGURATION_TYPES = ["PRIVATE", "EDGE", "REGIONAL"]
+
 
 class APIGatewayResponse(BaseResponse):
     def error(self, type_, message, status=400):
@@ -45,7 +48,45 @@ def restapis(self, request, full_url, headers):
         elif self.method == "POST":
             name = self._get_param("name")
             description = self._get_param("description")
-            rest_api = self.backend.create_rest_api(name, description)
+            api_key_source = self._get_param("apiKeySource")
+            endpoint_configuration = self._get_param("endpointConfiguration")
+            tags = self._get_param("tags")
+
+            # Param validation
+            if api_key_source and api_key_source not in API_KEY_SOURCES:
+                return self.error(
+                    "ValidationException",
+                    (
+                        "1 validation error detected: "
+                        "Value '{api_key_source}' at 'createRestApiInput.apiKeySource' failed "
+                        "to satisfy constraint: Member must satisfy enum value set: "
+                        "[AUTHORIZER, HEADER]"
+                    ).format(api_key_source=api_key_source),
+                )
+
+            if endpoint_configuration and "types" in endpoint_configuration:
+                invalid_types = list(
+                    set(endpoint_configuration["types"])
+                    - set(ENDPOINT_CONFIGURATION_TYPES)
+                )
+                if invalid_types:
+                    return self.error(
+                        "ValidationException",
+                        (
+                            "1 validation error detected: Value '{endpoint_type}' "
+                            "at 'createRestApiInput.endpointConfiguration.types' failed "
+                            "to satisfy constraint: Member must satisfy enum value set: "
+                            "[PRIVATE, EDGE, REGIONAL]"
+                        ).format(endpoint_type=invalid_types[0]),
+                    )
+
+            rest_api = self.backend.create_rest_api(
+                name,
+                description,
+                api_key_source=api_key_source,
+                endpoint_configuration=endpoint_configuration,
+                tags=tags,
+            )
             return 200, {}, json.dumps(rest_api.to_dict())
 
     def restapis_individual(self, request, full_url, headers):


Test patch:
diff --git a/tests/test_apigateway/test_apigateway.py b/tests/test_apigateway/test_apigateway.py
--- a/tests/test_apigateway/test_apigateway.py
+++ b/tests/test_apigateway/test_apigateway.py
@@ -26,7 +26,14 @@ def test_create_and_get_rest_api():
     response.pop("ResponseMetadata")
     response.pop("createdDate")
     response.should.equal(
-        {"id": api_id, "name": "my_api", "description": "this is my api"}
+        {
+            "id": api_id,
+            "name": "my_api",
+            "description": "this is my api",
+            "apiKeySource": "HEADER",
+            "endpointConfiguration": {"types": ["EDGE"]},
+            "tags": {},
+        }
     )
 
 
@@ -47,6 +54,114 @@ def test_list_and_delete_apis():
     len(response["items"]).should.equal(1)
 
 
+@mock_apigateway
+def test_create_rest_api_with_tags():
+    client = boto3.client("apigateway", region_name="us-west-2")
+
+    response = client.create_rest_api(
+        name="my_api", description="this is my api", tags={"MY_TAG1": "MY_VALUE1"}
+    )
+    api_id = response["id"]
+
+    response = client.get_rest_api(restApiId=api_id)
+
+    assert "tags" in response
+    response["tags"].should.equal({"MY_TAG1": "MY_VALUE1"})
+
+
+@mock_apigateway
+def test_create_rest_api_invalid_apikeysource():
+    client = boto3.client("apigateway", region_name="us-west-2")
+
+    with assert_raises(ClientError) as ex:
+        client.create_rest_api(
+            name="my_api",
+            description="this is my api",
+            apiKeySource="not a valid api key source",
+        )
+    ex.exception.response["Error"]["Code"].should.equal("ValidationException")
+
+
+@mock_apigateway
+def test_create_rest_api_valid_apikeysources():
+    client = boto3.client("apigateway", region_name="us-west-2")
+
+    # 1. test creating rest api with HEADER apiKeySource
+    response = client.create_rest_api(
+        name="my_api", description="this is my api", apiKeySource="HEADER",
+    )
+    api_id = response["id"]
+
+    response = client.get_rest_api(restApiId=api_id)
+    response["apiKeySource"].should.equal("HEADER")
+
+    # 2. test creating rest api with AUTHORIZER apiKeySource
+    response = client.create_rest_api(
+        name="my_api2", description="this is my api", apiKeySource="AUTHORIZER",
+    )
+    api_id = response["id"]
+
+    response = client.get_rest_api(restApiId=api_id)
+    response["apiKeySource"].should.equal("AUTHORIZER")
+
+
+@mock_apigateway
+def test_create_rest_api_invalid_endpointconfiguration():
+    client = boto3.client("apigateway", region_name="us-west-2")
+
+    with assert_raises(ClientError) as ex:
+        client.create_rest_api(
+            name="my_api",
+            description="this is my api",
+            endpointConfiguration={"types": ["INVALID"]},
+        )
+    ex.exception.response["Error"]["Code"].should.equal("ValidationException")
+
+
+@mock_apigateway
+def test_create_rest_api_valid_endpointconfigurations():
+    client = boto3.client("apigateway", region_name="us-west-2")
+
+    # 1. test creating rest api with PRIVATE endpointConfiguration
+    response = client.create_rest_api(
+        name="my_api",
+        description="this is my api",
+        endpointConfiguration={"types": ["PRIVATE"]},
+    )
+    api_id = response["id"]
+
+    response = client.get_rest_api(restApiId=api_id)
+    response["endpointConfiguration"].should.equal(
+        {"types": ["PRIVATE"],}
+    )
+
+    # 2. test creating rest api with REGIONAL endpointConfiguration
+    response = client.create_rest_api(
+        name="my_api2",
+        description="this is my api",
+        endpointConfiguration={"types": ["REGIONAL"]},
+    )
+    api_id = response["id"]
+
+    response = client.get_rest_api(restApiId=api_id)
+    response["endpointConfiguration"].should.equal(
+        {"types": ["REGIONAL"],}
+    )
+
+    # 3. test creating rest api with EDGE endpointConfiguration
+    response = client.create_rest_api(
+        name="my_api3",
+        description="this is my api",
+        endpointConfiguration={"types": ["EDGE"]},
+    )
+    api_id = response["id"]
+
+    response = client.get_rest_api(restApiId=api_id)
+    response["endpointConfiguration"].should.equal(
+        {"types": ["EDGE"],}
+    )
+
+
 @mock_apigateway
 def test_create_resource__validate_name():
     client = boto3.client("apigateway", region_name="us-west-2")