def test_uninstall(aws_credentials, mock_function_config):
    mock_session = MagicMock()
    mock_session.region_name = "us-east-1"
    mock_client = mock_session.client.return_value
    mock_client.get_function.return_value = None
    assert uninstall(layer_uninstall(session=mock_session), "foobarbaz") is False

    mock_client.get_function.reset_mock(return_value=True)
    config = mock_function_config("not.a.runtime")
    mock_client.get_function.return_value = config
    assert uninstall(layer_uninstall(session=mock_session), "foobarbaz") is True

    mock_client.get_function.reset_mock(return_value=True)
    config = mock_function_config("python3.7")
    mock_client.get_function.return_value = config
    assert uninstall(layer_uninstall(session=mock_session), "foobarbaz") is False

    config["Configuration"]["Handler"] = "newrelic_lambda_wrapper.handler"
    config["Configuration"]["Environment"]["Variables"][
        "NEW_RELIC_LAMBDA_HANDLER"
    ] = "foobar.handler"
    config["Configuration"]["Layers"] = [{"Arn": get_arn_prefix("us-east-1")}]
    assert uninstall(layer_uninstall(session=mock_session), "foobarbaz") is True

    mock_client.assert_has_calls([call.get_function(FunctionName="foobarbaz")])
    mock_client.assert_has_calls(
        [
            call.update_function_configuration(
                FunctionName="arn:aws:lambda:us-east-1:5558675309:function:aws-python3-dev-hello",  # noqa
                Handler="foobar.handler",
                Environment={"Variables": {"EXISTING_ENV_VAR": "Hello World"}},
                Layers=[],
            )
        ]
    )
Esempio n. 2
0
def _remove_new_relic(config, region):
    runtime = config["Configuration"]["Runtime"]
    if runtime not in utils.RUNTIME_CONFIG:
        failure(
            "Unsupported Lambda runtime for '%s': %s"
            % (config["Configuration"]["FunctionArn"], runtime)
        )
        return

    handler = config["Configuration"]["Handler"]

    # Detect non-New Relic handler and error if necessary.
    if not utils.is_valid_handler(runtime, handler):
        failure(
            "New Relic installation (via layers) not auto-detected for the specified "
            "function '%s'. Unrecognized handler in deployed function."
            % config["Configuration"]["FunctionArn"]
        )
        return

    env_handler = (
        config["Configuration"]
        .get("Environment", {})
        .get("Variables", {})
        .get("NEW_RELIC_LAMBDA_HANDLER")
    )

    if not env_handler:
        failure(
            "New Relic installation (via layers) not auto-detected for the specified "
            "function '%s'. Environment variable NEW_RELIC_LAMBDA_HANDLER not found."
            % config["Configuration"]["FunctionArn"]
        )
        return

    # Delete New Relic env vars
    config["Configuration"]["Environment"]["Variables"] = {
        key: value
        for key, value in config["Configuration"]
        .get("Environment", {})
        .get("Variables", {})
        .items()
        if not key.startswith("NEW_RELIC")
    }

    # Remove New Relic layers
    layers = [
        layer["Arn"]
        for layer in config["Configuration"].get("Layers")
        if not layer["Arn"].startswith(utils.get_arn_prefix(region))
    ]

    return {
        "FunctionName": config["Configuration"]["FunctionArn"],
        "Handler": env_handler,
        "Environment": config["Configuration"]["Environment"],
        "Layers": layers,
    }
Esempio n. 3
0
def _remove_new_relic(input, config):
    assert isinstance(input, LayerUninstall)

    aws_region = input.session.region_name

    runtime = config["Configuration"]["Runtime"]
    if runtime not in utils.RUNTIME_CONFIG:
        failure("Unsupported Lambda runtime for '%s': %s" %
                (config["Configuration"]["FunctionArn"], runtime))
        return True

    handler = config["Configuration"]["Handler"]

    # For java runtimes we need to remove the method name before
    # validating because method names are variable
    if "java" in runtime:
        handler = handler.split("::", 1)[0] + "::"

    # Detect non-New Relic handler and error if necessary.
    if not utils.is_valid_handler(runtime, handler):
        failure(
            "New Relic installation (via layers) not auto-detected for the specified "
            "function '%s'. Unrecognized handler in deployed function." %
            config["Configuration"]["FunctionArn"])
        return False

    env_handler = (config["Configuration"].get("Environment", {}).get(
        "Variables", {}).get("NEW_RELIC_LAMBDA_HANDLER"))

    # Delete New Relic env vars
    config["Configuration"]["Environment"]["Variables"] = {
        key: value
        for key, value in config["Configuration"].get("Environment", {}).get(
            "Variables", {}).items() if key not in NEW_RELIC_ENV_VARS
    }

    # Remove New Relic layers
    layers = [
        layer["Arn"] for layer in config["Configuration"].get("Layers")
        if not layer["Arn"].startswith(utils.get_arn_prefix(aws_region))
    ]

    return {
        "FunctionName":
        config["Configuration"]["FunctionArn"],
        "Handler":
        env_handler if env_handler else config["Configuration"]["Handler"],
        "Environment":
        config["Configuration"]["Environment"],
        "Layers":
        layers,
    }
Esempio n. 4
0
def list_functions(session, filter=None):
    client = session.client("lambda")

    all = filter == "all" or not filter

    pager = client.get_paginator("list_functions")
    for res in pager.paginate():
        funcs = res.get("Functions", [])
        for func in funcs:
            func.setdefault("x-new-relic-enabled", False)
            for layer in func.get("Layers", []):
                if layer.get("Arn", "").startswith(
                        utils.get_arn_prefix(session.region_name)):
                    func["x-new-relic-enabled"] = True
            if all:
                yield func
            elif filter == "installed" and func["x-new-relic-enabled"]:
                yield func
            elif filter == "not-installed" and not func["x-new-relic-enabled"]:
                yield func
Esempio n. 5
0
def list_functions(session, filter_choice):
    client = session.client("lambda")

    # set all if the filter_choice is "all" or there is no filter_choice active.
    all = filter_choice == "all" or not filter_choice

    pager = client.get_paginator("list_functions")
    for func_resp in pager.paginate():
        funcs = func_resp.get("Functions", [])

        for f in funcs:
            f.setdefault("x-new-relic-enabled", False)
            for layer in f.get("Layers", []):
                if layer.get("Arn", "").startswith(
                        utils.get_arn_prefix(session.region_name)):
                    f["x-new-relic-enabled"] = True
            if all:
                yield f
            elif filter_choice == "installed" and f["x-new-relic-enabled"]:
                yield f
            elif filter_choice == "not_installed" and not f[
                    "x-new-relic-enabled"]:
                yield f
Esempio n. 6
0
def _add_new_relic(config, region, layer_arn, account_id, allow_upgrade):
    runtime = config["Configuration"]["Runtime"]
    if runtime not in utils.RUNTIME_CONFIG:
        raise click.UsageError("Unsupported Lambda runtime: %s" % runtime)

    handler = config["Configuration"]["Handler"]
    runtime_handler = utils.RUNTIME_CONFIG.get(runtime, {}).get("Handler")
    if not allow_upgrade and handler == runtime_handler:
        raise click.UsageError(
            "Already installed. Pass --upgrade (or -u) to allow upgrade or "
            "reinstall to latest layer version.")

    existing_layers = [
        layer["Arn"] for layer in config["Configuration"].get("Layers", [])
        if not layer["Arn"].startswith(utils.get_arn_prefix(region))
    ]

    new_relic_layers = []
    if layer_arn:
        new_relic_layers = [layer_arn]
    else:
        # discover compatible layers...
        available_layers = index(region, runtime)

        # TODO: MAke this a layer selection screen
        if len(available_layers) > 1:
            message = ["Discovered layers for runtime (%s)" % runtime]
            for layer in available_layers:
                message.append("%s\t%s" % (
                    layer["LatestMatchingVersion"]["LayerVersionArn"],
                    layer.get("Description", ""),
                ))
            message.append(
                "\nMultiple layers found. Pass --layer-arn to specify layer ARN"
            )
            raise click.UsageError("\n".join(message))

        new_relic_layers = [
            available_layers[0]["LatestMatchingVersion"]["LayerVersionArn"]
        ]

    update_kwargs = {
        "FunctionName": config["Configuration"]["FunctionArn"],
        "Handler": runtime_handler,
        "Environment": {
            "Variables":
            config["Configuration"].get("Environment",
                                        {}).get("Variables", {})
        },
        "Layers": new_relic_layers + existing_layers,
    }

    # Update the account id
    update_kwargs["Environment"]["Variables"]["NEW_RELIC_ACCOUNT_ID"] = str(
        account_id)

    # Update the NEW_RELIC_LAMBDA_HANDLER envvars only when it's a new install.
    if handler != runtime_handler:
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_LAMBDA_HANDLER"] = handler

    return update_kwargs
Esempio n. 7
0
def _add_new_relic(input, config, nr_license_key):
    assert isinstance(input, LayerInstall)

    aws_region = input.session.region_name

    runtime = config["Configuration"]["Runtime"]
    if runtime not in utils.RUNTIME_CONFIG:
        failure("Unsupported Lambda runtime for '%s': %s" %
                (config["Configuration"]["FunctionArn"], runtime))
        return True

    handler = config["Configuration"]["Handler"]
    runtime_handler = utils.RUNTIME_CONFIG.get(runtime, {}).get("Handler")

    existing_newrelic_layer = [
        layer["Arn"] for layer in config["Configuration"].get("Layers", [])
        if layer["Arn"].startswith(utils.get_arn_prefix(aws_region))
    ]

    if not input.upgrade and existing_newrelic_layer:
        success(
            "Already installed on function '%s'. Pass --upgrade (or -u) to allow "
            "upgrade or reinstall to latest layer version." %
            config["Configuration"]["FunctionArn"])
        return True

    existing_layers = [
        layer["Arn"] for layer in config["Configuration"].get("Layers", [])
        if not layer["Arn"].startswith(utils.get_arn_prefix(aws_region))
    ]

    new_relic_layers = []

    if input.layer_arn:
        new_relic_layers = [input.layer_arn]
    else:
        # discover compatible layers...
        available_layers = index(aws_region, runtime)

        if not available_layers:
            failure("No Lambda layers published for '%s' runtime: %s" %
                    (config["Configuration"]["FunctionArn"], runtime))
            return False

        # TODO: MAke this a layer selection screen
        if len(available_layers) > 1:
            message = ["Discovered layers for runtime (%s)" % runtime]
            for layer in available_layers:
                message.append("%s\t%s" % (
                    layer["LatestMatchingVersion"]["LayerVersionArn"],
                    layer.get("Description", ""),
                ))
            message.append(
                "\nMultiple layers found. Pass --layer-arn to specify layer ARN"
            )
            raise click.UsageError("\n".join(message))

        new_relic_layers = [
            available_layers[0]["LatestMatchingVersion"]["LayerVersionArn"]
        ]

    update_kwargs = {
        "FunctionName": config["Configuration"]["FunctionArn"],
        "Environment": {
            "Variables":
            config["Configuration"].get("Environment",
                                        {}).get("Variables", {})
        },
        "Layers": new_relic_layers + existing_layers,
    }

    # Only used by Python and Node.js runtimes
    if runtime_handler:
        update_kwargs["Handler"] = runtime_handler

    # Update the account id
    update_kwargs["Environment"]["Variables"]["NEW_RELIC_ACCOUNT_ID"] = str(
        input.nr_account_id)

    # Update the NEW_RELIC_LAMBDA_HANDLER envvars only when it's a new install.
    if runtime_handler and handler != runtime_handler:
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_LAMBDA_HANDLER"] = handler

    if input.enable_extension:
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_LAMBDA_EXTENSION_ENABLED"] = "true"

        if input.enable_extension_function_logs:
            update_kwargs["Environment"]["Variables"][
                "NEW_RELIC_EXTENSION_SEND_FUNCTION_LOGS"] = "true"
        else:
            update_kwargs["Environment"]["Variables"][
                "NEW_RELIC_EXTENSION_SEND_FUNCTION_LOGS"] = "false"

        if input.nr_region == "staging":
            update_kwargs["Environment"]["Variables"][
                "NEW_RELIC_TELEMETRY_ENDPOINT"] = "https://staging-cloud-collector.newrelic.com/aws/lambda/v1"
            update_kwargs["Environment"]["Variables"][
                "NEW_RELIC_LOG_ENDPOINT"] = "https://staging-log-api.newrelic.com/log/v1"

        if nr_license_key:
            update_kwargs["Environment"]["Variables"][
                "NEW_RELIC_LICENSE_KEY"] = nr_license_key
    else:
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_LAMBDA_EXTENSION_ENABLED"] = "false"

    return update_kwargs
def test_add_new_relic(aws_credentials, mock_function_config):
    session = boto3.Session(region_name="us-east-1")

    config = mock_function_config("python3.7")

    assert config["Configuration"]["Handler"] == "original_handler"

    update_kwargs = _add_new_relic(
        layer_install(
            session=session,
            aws_region="us-east-1",
            nr_account_id=12345,
            enable_extension=True,
            enable_extension_function_logs=True,
        ),
        config,
        nr_license_key=None,
    )

    assert update_kwargs["FunctionName"] == config["Configuration"]["FunctionArn"]
    assert update_kwargs["Handler"] == "newrelic_lambda_wrapper.handler"
    assert update_kwargs["Environment"]["Variables"]["NEW_RELIC_ACCOUNT_ID"] == "12345"
    assert (
        update_kwargs["Environment"]["Variables"]["NEW_RELIC_LAMBDA_HANDLER"]
        == config["Configuration"]["Handler"]
    )
    assert (
        update_kwargs["Environment"]["Variables"]["NEW_RELIC_LAMBDA_EXTENSION_ENABLED"]
        == "true"
    )
    assert (
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_EXTENSION_SEND_FUNCTION_LOGS"
        ]
        == "true"
    )

    config = mock_function_config("not.a.runtime")
    assert (
        _add_new_relic(
            layer_install(
                session=session,
                aws_region="us-east-1",
                nr_account_id=12345,
                enable_extension=True,
                enable_extension_function_logs=True,
            ),
            config,
            nr_license_key=None,
        )
        is True
    )

    config = mock_function_config("python3.7")
    config["Configuration"]["Layers"] = [{"Arn": get_arn_prefix("us-east-1")}]
    assert (
        _add_new_relic(
            layer_install(
                session=session,
                aws_region="us-east-1",
                nr_account_id=12345,
                enable_extension=True,
                enable_extension_function_logs=True,
            ),
            config,
            nr_license_key=None,
        )
        is True
    )

    with patch("newrelic_lambda_cli.layers.index") as mock_index:
        mock_index.return_value = []
        config = mock_function_config("python3.7")
        assert (
            _add_new_relic(
                layer_install(
                    session=session,
                    aws_region="us-east-1",
                    nr_account_id=12345,
                    enable_extension=True,
                    enable_extension_function_logs=True,
                ),
                config,
                nr_license_key=None,
            )
            is False
        )

    # This shouldn't happen, but has, so we handle the case
    with patch("newrelic_lambda_cli.layers.index") as mock_index:
        mock_index.return_value = [
            {
                "LatestMatchingVersion": {
                    "LayerVersionArn": "arn:aws:lambda:us-east-1:123456789:layer/foobar"
                }
            },
            {
                "LatestMatchingVersion": {
                    "LayerVersionArn": "arn:aws:lambda:us-east-1:123456789:layer/barbaz"
                }
            },
        ]
        config = mock_function_config("python3.7")
        with pytest.raises(UsageError):
            _add_new_relic(
                layer_install(
                    session=session,
                    aws_region="us-east-1",
                    nr_account_id=12345,
                    enable_extension=True,
                    enable_extension_function_logs=True,
                ),
                config,
                nr_license_key=None,
            )

    config = mock_function_config("python3.7")
    _add_new_relic(
        layer_install(
            session=session,
            aws_region="us-east-1",
            nr_account_id=12345,
            nr_region="staging",
            enable_extension=True,
            enable_extension_function_logs=True,
        ),
        config,
        "foobarbaz",
    )
    assert (
        "NEW_RELIC_TELEMETRY_ENDPOINT"
        in config["Configuration"]["Environment"]["Variables"]
    )

    config = mock_function_config("python3.7")
    config["Configuration"]["Environment"]["Variables"]["NEW_RELIC_FOO"] = "bar"
    config["Configuration"]["Layers"] = [{"Arn": get_arn_prefix("us-east-1")}]
    update_kwargs = _add_new_relic(
        layer_install(
            session=session,
            aws_region="us-east-1",
            nr_account_id=12345,
            enable_extension=True,
            enable_extension_function_logs=True,
            upgrade=True,
        ),
        config,
        "foobarbaz",
    )
    assert "NEW_RELIC_FOO" in update_kwargs["Environment"]["Variables"]
    assert update_kwargs["Layers"][0] != get_arn_prefix("us-east-1")

    config = mock_function_config("python3.6")
    update_kwargs = _add_new_relic(
        layer_install(
            session=session,
            aws_region="us-east-1",
            nr_account_id=12345,
            enable_extension=True,
            enable_extension_function_logs=True,
            upgrade=True,
        ),
        config,
        "foobarbaz",
    )
    assert (
        update_kwargs["Environment"]["Variables"]["NEW_RELIC_LAMBDA_EXTENSION_ENABLED"]
        == "false"
    )
Esempio n. 9
0
def test_add_new_relic(aws_credentials, mock_function_config):
    session = boto3.Session(region_name="us-east-1")

    config = mock_function_config("python3.7")

    assert config["Configuration"]["Handler"] == "original_handler"

    update_kwargs = _add_new_relic(
        layer_install(
            session=session,
            aws_region="us-east-1",
            nr_account_id=12345,
            enable_extension=True,
            enable_extension_function_logs=True,
        ),
        config,
        nr_license_key=None,
    )

    assert update_kwargs["FunctionName"] == config["Configuration"]["FunctionArn"]
    assert update_kwargs["Handler"] == "newrelic_lambda_wrapper.handler"
    assert update_kwargs["Environment"]["Variables"]["NEW_RELIC_ACCOUNT_ID"] == "12345"
    assert (
        update_kwargs["Environment"]["Variables"]["NEW_RELIC_LAMBDA_HANDLER"]
        == config["Configuration"]["Handler"]
    )
    assert (
        update_kwargs["Environment"]["Variables"]["NEW_RELIC_LAMBDA_EXTENSION_ENABLED"]
        == "true"
    )
    assert (
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_EXTENSION_SEND_FUNCTION_LOGS"
        ]
        == "true"
    )

    config = mock_function_config("not.a.runtime")
    assert (
        _add_new_relic(
            layer_install(
                session=session,
                aws_region="us-east-1",
                nr_account_id=12345,
                enable_extension=True,
                enable_extension_function_logs=True,
            ),
            config,
            nr_license_key=None,
        )
        is True
    )

    config = mock_function_config("python3.7")
    config["Configuration"]["Layers"] = [{"Arn": get_arn_prefix("us-east-1")}]
    assert (
        _add_new_relic(
            layer_install(
                session=session,
                aws_region="us-east-1",
                nr_account_id=12345,
                enable_extension=True,
                enable_extension_function_logs=True,
            ),
            config,
            nr_license_key=None,
        )
        is True
    )

    with patch("newrelic_lambda_cli.layers.index") as mock_index:
        mock_index.return_value = []
        config = mock_function_config("python3.7")
        assert (
            _add_new_relic(
                layer_install(
                    session=session,
                    aws_region="us-east-1",
                    nr_account_id=12345,
                    enable_extension=True,
                    enable_extension_function_logs=True,
                ),
                config,
                nr_license_key=None,
            )
            is False
        )

    with patch("newrelic_lambda_cli.layers.index") as mock_index:
        with patch(
            "newrelic_lambda_cli.layers.layer_selection"
        ) as layer_selection_mock:
            mock_index.return_value = [
                {
                    "LatestMatchingVersion": {
                        "LayerVersionArn": "arn:aws:lambda:us-east-1:123456789:layer/javajava"
                    }
                },
                {
                    "LatestMatchingVersion": {
                        "LayerVersionArn": "arn:aws:lambda:us-east-1:123456789:layer/NewRelicLambdaExtension"
                    }
                },
            ]
            layer_selection_mock.return_value = [
                "arn:aws:lambda:us-east-1:123456789:layer/NewRelicLambdaExtension"
            ]

            config = mock_function_config("java11")
            _add_new_relic(
                layer_install(
                    session=session,
                    aws_region="us-east-1",
                    nr_account_id=12345,
                    enable_extension=True,
                    enable_extension_function_logs=True,
                ),
                config,
                nr_license_key=None,
            )

            layer_selection_mock.assert_called_with(
                mock_index.return_value, "java11", "x86_64"
            )
            assert "original_handler" in config["Configuration"]["Handler"]

            # Java handler testing
            layer_selection_mock.return_value = [
                "arn:aws:lambda:us-east-1:123456789:layer/javajava"
            ]

            update_kwargs = _add_new_relic(
                layer_install(
                    session=session,
                    aws_region="us-east-1",
                    nr_account_id=12345,
                    enable_extension=True,
                    enable_extension_function_logs=True,
                ),
                config,
                nr_license_key=None,
            )
            assert (
                "com.newrelic.java.HandlerWrapper::handleRequest"
                in update_kwargs["Handler"]
            )
            assert (
                "original_handler"
                in update_kwargs["Environment"]["Variables"]["NEW_RELIC_LAMBDA_HANDLER"]
            )

    mock_layers = [
        {
            "LatestMatchingVersion": {
                "LayerVersionArn": "arn:aws:lambda:us-east-1:123456789:layer/javajava"
            }
        },
        {
            "LatestMatchingVersion": {
                "LayerVersionArn": "arn:aws:lambda:us-east-1:123456789:layer/NewRelicLambdaExtension"
            }
        },
    ]

    with patch("newrelic_lambda_cli.layers.click.prompt") as mock_prompt, patch(
        "sys.stdout.isatty"
    ) as mock_isatty:
        mock_isatty.return_value = True
        mock_prompt.return_value = 0
        result = layer_selection(mock_layers, "python3.7", "x86_64")
        assert result == "arn:aws:lambda:us-east-1:123456789:layer/javajava"

    with patch("sys.stdout.isatty") as mock_isatty:
        mock_isatty.return_value = False
        with pytest.raises(UsageError):
            layer_selection(mock_layers, "python3.7", "x86_64")

    config = mock_function_config("python3.7")
    _add_new_relic(
        layer_install(
            session=session,
            aws_region="us-east-1",
            nr_account_id=12345,
            nr_region="staging",
            enable_extension=True,
            enable_extension_function_logs=True,
        ),
        config,
        "foobarbaz",
    )
    assert (
        "NEW_RELIC_TELEMETRY_ENDPOINT"
        in config["Configuration"]["Environment"]["Variables"]
    )

    config = mock_function_config("python3.7")
    config["Configuration"]["Environment"]["Variables"]["NEW_RELIC_FOO"] = "bar"
    config["Configuration"]["Layers"] = [{"Arn": get_arn_prefix("us-east-1")}]
    update_kwargs = _add_new_relic(
        layer_install(
            session=session,
            aws_region="us-east-1",
            nr_account_id=12345,
            enable_extension=True,
            enable_extension_function_logs=True,
            upgrade=True,
        ),
        config,
        "foobarbaz",
    )
    assert "NEW_RELIC_FOO" in update_kwargs["Environment"]["Variables"]
    assert update_kwargs["Layers"][0] != get_arn_prefix("us-east-1")

    config = mock_function_config("python3.6")
    update_kwargs = _add_new_relic(
        layer_install(
            session=session,
            aws_region="us-east-1",
            nr_account_id=12345,
            enable_extension=True,
            enable_extension_function_logs=True,
            upgrade=True,
        ),
        config,
        "foobarbaz",
    )
    assert (
        update_kwargs["Environment"]["Variables"]["NEW_RELIC_LAMBDA_EXTENSION_ENABLED"]
        == "false"
    )
Esempio n. 10
0
def _add_new_relic(input, config, nr_license_key):
    assert isinstance(input, LayerInstall)

    aws_region = input.session.region_name

    runtime = config["Configuration"]["Runtime"]
    if runtime not in utils.RUNTIME_CONFIG:
        failure("Unsupported Lambda runtime for '%s': %s" %
                (config["Configuration"]["FunctionArn"], runtime))
        return True

    architectures = config["Configuration"].get("Architectures", ["x86_64"])
    architecture = architectures[0]

    handler = config["Configuration"]["Handler"]
    runtime_handler = utils.RUNTIME_CONFIG.get(runtime, {}).get("Handler")

    if "java" in runtime:
        postfix = input.java_handler_method or "handleRequest"
        runtime_handler = runtime_handler + postfix

    existing_newrelic_layer = [
        layer["Arn"] for layer in config["Configuration"].get("Layers", [])
        if layer["Arn"].startswith(utils.get_arn_prefix(aws_region))
    ]

    if not input.upgrade and existing_newrelic_layer:
        success(
            "Already installed on function '%s'. Pass --upgrade (or -u) to allow "
            "upgrade or reinstall to latest layer version." %
            config["Configuration"]["FunctionArn"])
        return True

    existing_layers = [
        layer["Arn"] for layer in config["Configuration"].get("Layers", [])
        if not layer["Arn"].startswith(utils.get_arn_prefix(aws_region))
    ]

    new_relic_layer = []

    if input.layer_arn:
        new_relic_layer = input.layer_arn
    else:
        # discover compatible layers...
        available_layers = index(aws_region, runtime, architecture)

        if not available_layers:
            failure("No Lambda layers published for %s (%s) runtime: %s" %
                    (config["Configuration"]["FunctionArn"], runtime,
                     architecture))
            return False

        new_relic_layer = layer_selection(available_layers, runtime,
                                          architecture)

    update_kwargs = {
        "FunctionName": config["Configuration"]["FunctionArn"],
        "Environment": {
            "Variables":
            config["Configuration"].get("Environment",
                                        {}).get("Variables", {})
        },
        "Layers": [new_relic_layer] + existing_layers,
    }

    # We don't want to modify the handler if the NewRelicLambdaExtension layer
    # has been selected
    if any("NewRelicLambdaExtension" in s for s in new_relic_layer):
        runtime_handler = None

    # Only used by Python, Node.js and Java runtimes not using the
    # NewRelicLambdaExtension layer
    if runtime_handler:
        update_kwargs["Handler"] = runtime_handler

    # Update the account id
    update_kwargs["Environment"]["Variables"]["NEW_RELIC_ACCOUNT_ID"] = str(
        input.nr_account_id)

    # Update the NEW_RELIC_LAMBDA_HANDLER envvars only when it's a new install.
    if runtime_handler and handler != runtime_handler:
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_LAMBDA_HANDLER"] = handler

    if input.enable_extension and not utils.supports_lambda_extension(runtime):
        warning(
            "The %s runtime for %s does not support Lambda Extensions, reverting to a "
            "CloudWatch Logs based ingestion. Make sure you run `newrelic-lambda "
            "integrations install` command to install the New Relic log ingestion "
            "function and `newrelic-lambda subscriptions install` to create the log "
            "subscription filter." %
            (runtime, config["Configuration"]["FunctionName"]))

    if input.enable_extension and utils.supports_lambda_extension(runtime):
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_LAMBDA_EXTENSION_ENABLED"] = "true"

        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_EXTENSION_SEND_FUNCTION_LOGS"] = (
                "true" if input.enable_extension_function_logs else "false")

        if input.nr_region == "staging":
            update_kwargs["Environment"]["Variables"][
                "NEW_RELIC_TELEMETRY_ENDPOINT"] = "https://staging-cloud-collector.newrelic.com/aws/lambda/v1"
            update_kwargs["Environment"]["Variables"][
                "NEW_RELIC_LOG_ENDPOINT"] = "https://staging-log-api.newrelic.com/log/v1"

        if nr_license_key:
            update_kwargs["Environment"]["Variables"][
                "NEW_RELIC_LICENSE_KEY"] = nr_license_key
    else:
        update_kwargs["Environment"]["Variables"][
            "NEW_RELIC_LAMBDA_EXTENSION_ENABLED"] = "false"

    return update_kwargs