Core: Add endpoint to configure Dockerless services in ServerMode (#7393)

This commit is contained in:
Bert Blommers 2024-02-26 09:36:25 +00:00 committed by GitHub
parent dbfa456dda
commit 89a85cf454
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 115 additions and 1 deletions

View File

@ -20,7 +20,8 @@ If you are using the decorators, some options are configurable within the decora
"services": ["dynamodb"]
},
"reset_boto3_session": True,
}
},
"iam": {"load_aws_managed_policies": False},
})
@ -49,6 +50,36 @@ That is why Moto resets the `boto3-Session`, to make sure that it is recreated w
If all of your tests use Moto, and you never want to reach out to AWS, you can choose to _not_ reset the `boto3-session`. New boto3-clients that are created will reuse the `boto3-Session` (with fake credentials), making Moto much more performant.
AWS Managed Policies
--------------------
Moto comes bundled with all Managed Policies that AWS exposes, which are updated regularly. However, they are not loaded unless specifically requested for performance reasons.
Set `"iam": {"load_aws_managed_policies": True}` to load these policies for a single test.
Configuring MotoServer
----------------------
The following options can also be configured when running the MotoServer:
.. sourcecode::
options = {
"batch": {"use_docker": True},
"lambda": {"use_docker": True}
}
requests.post(f"http://localhost:5000/moto-api/config", json=options)
Send a GET request to see the current status of this configuration:
.. sourcecode::
requests.get(f"http://localhost:5000/moto-api/config").json()
The IAM Managed Policies should be loaded with an environment variable:
.. sourcecode::
MOTO_IAM_LOAD_MANAGED_POLICIES=true
Other configuration options
---------------------------

View File

@ -2,6 +2,7 @@ from typing import Any, Dict, List, Optional, Set, Tuple
from moto.core import DEFAULT_ACCOUNT_ID
from moto.core.base_backend import BackendDict, BaseBackend
from moto.core.config import default_user_config
from moto.core.model_instances import reset_model_data
@ -116,5 +117,17 @@ class MotoAPIBackend(BaseBackend):
self.proxy_urls_to_passthrough.clear()
self.proxy_hosts_to_passthrough.clear()
def get_config(self) -> Dict[str, Any]:
return {
"batch": default_user_config["batch"],
"lambda": default_user_config["lambda"],
}
def set_config(self, config: Dict[str, Any]) -> None:
if "batch" in config:
default_user_config["batch"] = config["batch"]
if "lambda" in config:
default_user_config["lambda"] = config["lambda"]
moto_api_backend = MotoAPIBackend(region_name="global", account_id=DEFAULT_ACCOUNT_ID)

View File

@ -277,6 +277,23 @@ class MotoAPIResponse(BaseResponse):
resp = {"http_urls": list(urls), "https_hosts": list(hosts)}
return 201, res_headers, json.dumps(resp).encode("utf-8")
def config(
self,
request: Any,
full_url: str, # pylint: disable=unused-argument
headers: Any,
) -> TYPE_RESPONSE:
from .models import moto_api_backend
res_headers = {"Content-Type": "application/json"}
if request.method == "POST":
config = self._get_body(headers, request)
moto_api_backend.set_config(config)
config = moto_api_backend.get_config()
return 201, res_headers, json.dumps(config).encode("utf-8")
def _get_body(self, headers: Any, request: Any) -> Any:
if isinstance(request, AWSPreparedRequest):
return json.loads(request.body) # type: ignore[arg-type]

View File

@ -13,6 +13,7 @@ url_paths = {
"{0}/moto-api/reset-auth": response_instance.reset_auth_response,
"{0}/moto-api/seed": response_instance.seed,
"{0}/moto-api/proxy/passthrough": response_instance.set_proxy_passthrough,
"{0}/moto-api/config": response_instance.config,
"{0}/moto-api/static/athena/query-results": response_instance.set_athena_result,
"{0}/moto-api/static/ce/cost-and-usage-results": response_instance.set_ce_cost_usage_result,
"{0}/moto-api/static/inspector2/findings-results": response_instance.set_inspector2_findings_result,

View File

@ -0,0 +1,52 @@
import requests
from moto import mock_aws, settings
from moto.awslambda.models import LambdaBackend
from moto.awslambda.utils import get_backend
from moto.awslambda_simple.models import LambdaSimpleBackend
from moto.core import DEFAULT_ACCOUNT_ID
from moto.core.config import default_user_config
@mock_aws
def test_change_configuration_using_api() -> None:
assert default_user_config["batch"] == {"use_docker": True}
assert default_user_config["lambda"] == {"use_docker": True}
base_url = (
"localhost:5000" if settings.TEST_SERVER_MODE else "motoapi.amazonaws.com"
)
resp = requests.get(f"http://{base_url}/moto-api/config")
assert resp.json()["batch"] == {"use_docker": True}
assert resp.json()["lambda"] == {"use_docker": True}
# Update a single configuration item
requests.post(
f"http://{base_url}/moto-api/config", json={"batch": {"use_docker": False}}
)
resp = requests.get(f"http://{base_url}/moto-api/config")
assert resp.json()["batch"] == {"use_docker": False}
assert resp.json()["lambda"] == {"use_docker": True}
if settings.TEST_DECORATOR_MODE:
isinstance(get_backend(DEFAULT_ACCOUNT_ID, "us-east-1"), LambdaBackend)
# Update multiple configuration items
requests.post(
f"http://{base_url}/moto-api/config",
json={"batch": {"use_docker": True}, "lambda": {"use_docker": False}},
)
resp = requests.get(f"http://{base_url}/moto-api/config")
assert resp.json()["batch"] == {"use_docker": True}
assert resp.json()["lambda"] == {"use_docker": False}
if settings.TEST_DECORATOR_MODE:
isinstance(get_backend(DEFAULT_ACCOUNT_ID, "us-east-1"), LambdaSimpleBackend)
# reset
requests.post(
f"http://{base_url}/moto-api/config",
json={"batch": {"use_docker": True}, "lambda": {"use_docker": True}},
)