def test_appconfig_force_update_new(appconfig_stub, mocker): client, stub, _ = appconfig_stub _add_start_stub(stub) stub.add_response( "get_latest_configuration", _build_response("hello", "text/plain"), _build_request(), ) stub.add_response( "get_latest_configuration", _build_response("world", "text/plain", next_token="token9012"), _build_request(next_token="token5678"), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) result = a.update_config() assert result assert a.config == "hello" assert a.raw_config == b"hello" assert a.content_type == "text/plain" assert a._next_config_token == "token5678" assert a._poll_interval == 30 result = a.update_config(force_update=True) assert result assert a.config == "world" assert a.raw_config == b"world" assert a.content_type == "text/plain" assert a._next_config_token == "token9012" assert a._poll_interval == 30
def test_appconfig_force_update_same(appconfig_stub, mocker): client, stub, _ = appconfig_stub stub.add_response( "get_configuration", _build_response("hello", "1", "text/plain"), _build_request(), ) stub.add_response( "get_configuration", _build_response("", "1", "text/plain"), _build_request(version="1"), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) result = a.update_config() assert result assert a.config == "hello" assert a.config_version == "1" assert a.raw_config == b"hello" assert a.content_type == "text/plain" result = a.update_config(force_update=True) assert not result assert a.config == "hello" assert a.config_version == "1" assert a.raw_config == b"hello" assert a.content_type == "text/plain"
def test_appconfig_fetch_no_change(appconfig_stub, mocker): with freeze_time("2020-08-01 12:00:00") as frozen_time: tick_amount = datetime.timedelta(seconds=10) client, stub, _ = appconfig_stub _add_start_stub(stub) stub.add_response( "get_latest_configuration", _build_response("hello", "text/plain", poll=15), _build_request(), ) stub.add_response( "get_latest_configuration", _build_response("", "text/plain", poll=15, next_token="token1234"), _build_request(next_token="token5678"), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) result = a.update_config() update_time = time.time() assert result assert a.config == "hello" assert a._last_update_time == update_time frozen_time.tick(tick_amount) frozen_time.tick(tick_amount) result = a.update_config() assert not result assert a.config == "hello" assert a._next_config_token == "token1234" assert a._last_update_time == time.time()
def test_appconfig_fetch_interval(appconfig_stub, mocker): client, stub, _ = appconfig_stub stub.add_response( "get_configuration", _build_response("hello", "1", "text/plain"), _build_request(), ) stub.add_response( "get_configuration", _build_response("world", "2", "text/plain"), _build_request(version="1"), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) result = a.update_config() assert result assert a.config == "hello" assert a.config_version == "1" result = a.update_config() assert not result assert a.config == "hello" assert a.config_version == "1" result = a.update_config() assert result assert a.config == "world" assert a.config_version == "2"
def test_bad_request(appconfig_stub_ignore_pending, mocker): client, stub, session = appconfig_stub_ignore_pending content_text = "hello world" _add_start_stub(stub, "", "", "") stub.add_response( "get_latest_configuration", _build_response(content_text, "image/jpeg"), _build_request(), ) mocker.patch.object(boto3, "client", return_value=client) with pytest.raises(botocore.exceptions.ParamValidationError): a = AppConfigHelper("", "", "", 15) a.update_config()
def test_appconfig_json(appconfig_stub, mocker): client, stub, _ = appconfig_stub _add_start_stub(stub) stub.add_response( "get_latest_configuration", _build_response({"hello": "world"}, "application/json"), _build_request(), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) a.update_config() assert a.config == {"hello": "world"} assert a.content_type == "application/json"
def test_appconfig_fetch_on_init(appconfig_stub, mocker): client, stub, _ = appconfig_stub _add_start_stub(stub) stub.add_response( "get_latest_configuration", _build_response("hello", "text/plain"), _build_request(), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15, fetch_on_init=True) assert a.config == "hello"
def test_appconfig_init(appconfig_stub, mocker): client, stub, _ = appconfig_stub mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) assert isinstance(a, AppConfigHelper) assert a.appconfig_application == "AppConfig-App" assert a.appconfig_environment == "AppConfig-Env" assert a.appconfig_profile == "AppConfig-Profile" assert a.config is None assert a.config_version == "null" assert a._last_update_time == 0.0 assert a.raw_config is None assert a.content_type is None
def test_appconfig_session(appconfig_stub, mocker): client, stub, session = appconfig_stub stub.add_response( "get_configuration", _build_response({"hello": "world"}, "1", "application/json"), _build_request(), ) mocker.patch.object(boto3, "client", return_value=client) mocker.patch.object(boto3.Session, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15, session=session) a.update_config()
def test_unknown_content_type(appconfig_stub, mocker): client, stub, session = appconfig_stub content_text = "hello world" _add_start_stub(stub) stub.add_response( "get_latest_configuration", _build_response(content_text, "image/jpeg"), _build_request(), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) a.update_config() assert a.config == b"hello world" assert a.content_type == "image/jpeg" assert a.raw_config == content_text.encode("utf-8")
def test_bad_json(appconfig_stub, mocker): client, stub, session = appconfig_stub content_text = """{"broken": "json",}""".encode("utf-8") _add_start_stub(stub) broken_response = _build_response({}, "application/json") broken_response["Configuration"] = StreamingBody( io.BytesIO(bytes(content_text)), len(content_text)) stub.add_response( "get_latest_configuration", broken_response, _build_request(), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) with pytest.raises(ValueError): a.update_config()
def test_bad_request(appconfig_stub_ignore_pendng, mocker): client, stub, session = appconfig_stub_ignore_pendng content_text = """hello world""".encode("utf-8") stub.add_response( "get_configuration", { "Content": StreamingBody(io.BytesIO(bytes(content_text)), len(content_text)), "ConfigurationVersion": "1", "ContentType": "image/jpeg", }, _build_request("", "", ""), ) mocker.patch.object(boto3, "client", return_value=client) with pytest.raises(botocore.exceptions.ParamValidationError): a = AppConfigHelper("", "", "", 15) a.update_config()
def test_unknown_content_type(appconfig_stub, mocker): client, stub, session = appconfig_stub content_text = """hello world""".encode("utf-8") stub.add_response( "get_configuration", { "Content": StreamingBody(io.BytesIO(bytes(content_text)), len(content_text)), "ConfigurationVersion": "1", "ContentType": "image/jpeg", }, _build_request(), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) a.update_config() assert a.config == b"hello world" assert a.content_type == "image/jpeg" assert a.raw_config == content_text
def test_appconfig_fetch_on_read(appconfig_stub, mocker): client, stub, _ = appconfig_stub _add_start_stub(stub) stub.add_response( "get_latest_configuration", _build_response("hello", "text/plain", poll=15), _build_request(), ) stub.add_response( "get_latest_configuration", _build_response("world", "text/plain", next_token="token9012"), _build_request(next_token="token5678"), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15, fetch_on_read=True) assert a.config == "hello" assert a._next_config_token == "token5678" assert a.config == "world" assert a._next_config_token == "token9012"
def test_bad_yaml(appconfig_stub, mocker): client, stub, session = appconfig_stub content_text = """ broken: - yaml - content """.encode("utf-8") stub.add_response( "get_configuration", { "Content": StreamingBody(io.BytesIO(bytes(content_text)), len(content_text)), "ConfigurationVersion": "1", "ContentType": "application/x-yaml", }, _build_request(), ) mocker.patch.object(boto3, "client", return_value=client) a = AppConfigHelper("AppConfig-App", "AppConfig-Env", "AppConfig-Profile", 15) with pytest.raises(ValueError): a.update_config()
def test_bad_interval(appconfig_stub, mocker): client, stub, session = appconfig_stub mocker.patch.object(boto3, "client", return_value=client) with pytest.raises(ValueError): _ = AppConfigHelper("Any", "Any", "Any", 10)
Example application for AppConfigHelper Create the required AppConfig resources with the CloudFormation template. Run this file with `uvicorn main:app` """ from fastapi import FastAPI from appconfig_helper import AppConfigHelper app = FastAPI() appconfig = AppConfigHelper( "DemoApp", "prod", "main", 15, ) @app.get("/process-string/{input_string}") def index(input_string): if appconfig.update_config(): print("Received new configuration") output_string = input_string if appconfig.config.get("transform_reverse", True): output_string = "".join(reversed(output_string)) if appconfig.config.get("transform_allcaps", False): output_string = output_string.upper() return {