newrelic-lambda-cli 0.9.6__tar.gz → 0.9.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/PKG-INFO +1 -1
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/layers.py +6 -2
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/layers.py +45 -4
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/types.py +1 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/utils.py +6 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/PKG-INFO +1 -1
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/setup.py +1 -1
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/tests/test_layers.py +69 -4
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/tests/test_utils.py +7 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/CODE_OF_CONDUCT.md +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/CONTRIBUTING.md +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/LICENSE +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/MANIFEST.in +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/README.md +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/THIRD_PARTY_NOTICES.md +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/__init__.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/api.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/__init__.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/decorators.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/functions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/integrations.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/otel_ingestions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/subscriptions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cliutils.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/functions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/integrations.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/otel_ingestions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/permissions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/subscriptions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/templates/import-template.yaml +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/templates/license-key-secret.yaml +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/templates/nr-lambda-integration-role.yaml +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/SOURCES.txt +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/dependency_links.txt +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/entry_points.txt +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/not-zip-safe +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/requires.txt +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/top_level.txt +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/pyproject.toml +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/setup.cfg +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/tests/test_api.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/tests/test_functions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/tests/test_integrations.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/tests/test_new_relic_gql.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/tests/test_permissions.py +0 -0
- {newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/tests/test_subscriptions.py +0 -0
|
@@ -81,6 +81,11 @@ def register(group):
|
|
|
81
81
|
help="Permit upgrade of function layers to new version.",
|
|
82
82
|
is_flag=True,
|
|
83
83
|
)
|
|
84
|
+
@click.option(
|
|
85
|
+
"--apm",
|
|
86
|
+
help="Enable APM Lambda mode",
|
|
87
|
+
is_flag=True,
|
|
88
|
+
)
|
|
84
89
|
@click.option(
|
|
85
90
|
"--enable-extension/--disable-extension",
|
|
86
91
|
"-x",
|
|
@@ -105,8 +110,7 @@ def register(group):
|
|
|
105
110
|
)
|
|
106
111
|
@click.option(
|
|
107
112
|
"--esm",
|
|
108
|
-
|
|
109
|
-
show_default=True,
|
|
113
|
+
is_flag=True,
|
|
110
114
|
help="Nodejs runtimes only - nodejs implementation runtime handler to /opt/nodejs/node_modules/newrelic-esm-lambda-wrapper/index.handler",
|
|
111
115
|
)
|
|
112
116
|
@click.pass_context
|
|
@@ -104,7 +104,7 @@ def _add_new_relic(input, config, nr_license_key):
|
|
|
104
104
|
prefix = (
|
|
105
105
|
"/opt/nodejs/node_modules/newrelic-esm-lambda-wrapper/index"
|
|
106
106
|
if input.esm
|
|
107
|
-
else "
|
|
107
|
+
else "newrelic-lambda-wrapper"
|
|
108
108
|
)
|
|
109
109
|
runtime_handler = prefix + ".handler"
|
|
110
110
|
|
|
@@ -118,6 +118,7 @@ def _add_new_relic(input, config, nr_license_key):
|
|
|
118
118
|
success(
|
|
119
119
|
"Already installed on function '%s'. Pass --upgrade (or -u) to allow "
|
|
120
120
|
"upgrade or reinstall to latest layer version."
|
|
121
|
+
"Additionally pass --apm to enable APM Lambda mode."
|
|
121
122
|
% config["Configuration"]["FunctionArn"]
|
|
122
123
|
)
|
|
123
124
|
return True
|
|
@@ -172,7 +173,18 @@ def _add_new_relic(input, config, nr_license_key):
|
|
|
172
173
|
|
|
173
174
|
# Update the NEW_RELIC_LAMBDA_HANDLER envvars only when it's a new install.
|
|
174
175
|
if runtime_handler and handler != runtime_handler:
|
|
175
|
-
|
|
176
|
+
if "nodejs" in runtime:
|
|
177
|
+
if handler not in [
|
|
178
|
+
"newrelic-lambda-wrapper.handler",
|
|
179
|
+
"/opt/nodejs/node_modules/newrelic-esm-lambda-wrapper/index.handler",
|
|
180
|
+
]:
|
|
181
|
+
update_kwargs["Environment"]["Variables"][
|
|
182
|
+
"NEW_RELIC_LAMBDA_HANDLER"
|
|
183
|
+
] = handler
|
|
184
|
+
else:
|
|
185
|
+
update_kwargs["Environment"]["Variables"][
|
|
186
|
+
"NEW_RELIC_LAMBDA_HANDLER"
|
|
187
|
+
] = handler
|
|
176
188
|
|
|
177
189
|
if input.enable_extension and not utils.supports_lambda_extension(runtime):
|
|
178
190
|
warning(
|
|
@@ -221,6 +233,13 @@ def _add_new_relic(input, config, nr_license_key):
|
|
|
221
233
|
"CORECLR_PROFILER_PATH"
|
|
222
234
|
] = "/opt/lib/newrelic-dotnet-agent/libNewRelicProfiler.so"
|
|
223
235
|
|
|
236
|
+
if input.apm:
|
|
237
|
+
success(
|
|
238
|
+
"Enabling APM Lambda mode for function '%s' "
|
|
239
|
+
% config["Configuration"]["FunctionArn"]
|
|
240
|
+
)
|
|
241
|
+
update_kwargs["Environment"]["Variables"]["NEW_RELIC_APM_LAMBDA_MODE"] = "True"
|
|
242
|
+
|
|
224
243
|
return update_kwargs
|
|
225
244
|
|
|
226
245
|
|
|
@@ -302,7 +321,25 @@ def install(input, function_arn):
|
|
|
302
321
|
if input.verbose:
|
|
303
322
|
click.echo(json.dumps(res, indent=2))
|
|
304
323
|
|
|
305
|
-
|
|
324
|
+
old_layers = config["Configuration"].get("Layers", [])
|
|
325
|
+
old_layer_arn = old_layers[0]["Arn"].rsplit(":", 1)[0] if old_layers else "None"
|
|
326
|
+
old_layer_version = (
|
|
327
|
+
old_layers[0]["Arn"].split(":")[-1] if old_layers else "None"
|
|
328
|
+
)
|
|
329
|
+
new_layer = update_kwargs["Layers"][0]
|
|
330
|
+
new_layer_arn = update_kwargs["Layers"][0].rsplit(":", 1)[0]
|
|
331
|
+
new_layer_version = update_kwargs["Layers"][0].split(":")[-1]
|
|
332
|
+
|
|
333
|
+
if old_layer_arn == "None":
|
|
334
|
+
success(
|
|
335
|
+
"Successfully installed Layer ARN %s for the function: %s"
|
|
336
|
+
% (new_layer, function_arn)
|
|
337
|
+
)
|
|
338
|
+
else:
|
|
339
|
+
success(
|
|
340
|
+
"Successfully upgraded Layer ARN %s from version: %s to version: %s for the function: %s"
|
|
341
|
+
% (new_layer_arn, old_layer_version, new_layer_version, function_arn)
|
|
342
|
+
)
|
|
306
343
|
return True
|
|
307
344
|
|
|
308
345
|
|
|
@@ -401,7 +438,11 @@ def uninstall(input, function_arn):
|
|
|
401
438
|
if input.verbose:
|
|
402
439
|
click.echo(json.dumps(res, indent=2))
|
|
403
440
|
|
|
404
|
-
|
|
441
|
+
old_layers = config["Configuration"].get("Layers", [])
|
|
442
|
+
old_layer_arn = old_layers[0]["Arn"] if old_layers else "None"
|
|
443
|
+
success(
|
|
444
|
+
"Successfully uninstalled Layer %s from %s" % (old_layer_arn, function_arn)
|
|
445
|
+
)
|
|
405
446
|
return True
|
|
406
447
|
|
|
407
448
|
|
|
@@ -131,6 +131,12 @@ def all_lambda_regions():
|
|
|
131
131
|
|
|
132
132
|
def is_valid_handler(runtime, handler):
|
|
133
133
|
runtime_handler = RUNTIME_CONFIG.get(runtime, {}).get("Handler", None)
|
|
134
|
+
if (
|
|
135
|
+
"nodejs" in runtime
|
|
136
|
+
and handler
|
|
137
|
+
== "/opt/nodejs/node_modules/newrelic-esm-lambda-wrapper/index.handler"
|
|
138
|
+
):
|
|
139
|
+
return True
|
|
134
140
|
if isinstance(runtime_handler, dict):
|
|
135
141
|
for _, valid_handler in runtime_handler.items():
|
|
136
142
|
if handler == valid_handler:
|
|
@@ -6,7 +6,7 @@ README = open(os.path.join(os.path.dirname(__file__), "README.md"), "r").read()
|
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name="newrelic-lambda-cli",
|
|
9
|
-
version="0.9.
|
|
9
|
+
version="0.9.8",
|
|
10
10
|
python_requires=">=3.3",
|
|
11
11
|
description="A CLI to install the New Relic AWS Lambda integration and layers.",
|
|
12
12
|
long_description=README,
|
|
@@ -235,6 +235,34 @@ def test_add_new_relic(aws_credentials, mock_function_config):
|
|
|
235
235
|
assert update_kwargs["Layers"][0] != get_arn_prefix("us-east-1")
|
|
236
236
|
|
|
237
237
|
|
|
238
|
+
@mock_aws
|
|
239
|
+
def test_add_new_relic_apm_lambda_mode(aws_credentials, mock_function_config):
|
|
240
|
+
session = boto3.Session(region_name="us-east-1")
|
|
241
|
+
|
|
242
|
+
config = mock_function_config("python3.12")
|
|
243
|
+
|
|
244
|
+
assert config["Configuration"]["Handler"] == "original_handler"
|
|
245
|
+
|
|
246
|
+
update_kwargs = _add_new_relic(
|
|
247
|
+
layer_install(
|
|
248
|
+
session=session,
|
|
249
|
+
aws_region="us-east-1",
|
|
250
|
+
nr_account_id=12345,
|
|
251
|
+
enable_extension=True,
|
|
252
|
+
enable_extension_function_logs=True,
|
|
253
|
+
apm=True,
|
|
254
|
+
),
|
|
255
|
+
config,
|
|
256
|
+
nr_license_key=None,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
assert update_kwargs["FunctionName"] == config["Configuration"]["FunctionArn"]
|
|
260
|
+
assert update_kwargs["Handler"] == "newrelic_lambda_wrapper.handler"
|
|
261
|
+
assert (
|
|
262
|
+
update_kwargs["Environment"]["Variables"]["NEW_RELIC_APM_LAMBDA_MODE"] == "True"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
|
|
238
266
|
@mock_aws
|
|
239
267
|
def test_add_new_relic_dotnet(aws_credentials, mock_function_config):
|
|
240
268
|
session = boto3.Session(region_name="us-east-1")
|
|
@@ -333,7 +361,7 @@ def test_add_new_relic_nodejs(aws_credentials, mock_function_config):
|
|
|
333
361
|
assert (
|
|
334
362
|
update_kwargs_std["FunctionName"] == config_std["Configuration"]["FunctionArn"]
|
|
335
363
|
)
|
|
336
|
-
assert update_kwargs_std["Handler"] == "
|
|
364
|
+
assert update_kwargs_std["Handler"] == "newrelic-lambda-wrapper.handler"
|
|
337
365
|
assert (
|
|
338
366
|
update_kwargs_std["Environment"]["Variables"]["NEW_RELIC_LAMBDA_HANDLER"]
|
|
339
367
|
== original_std_handler
|
|
@@ -633,7 +661,44 @@ def test_uninstall(aws_credentials, mock_function_config):
|
|
|
633
661
|
)
|
|
634
662
|
|
|
635
663
|
|
|
636
|
-
|
|
637
|
-
|
|
664
|
+
@mock_aws
|
|
665
|
+
def test_install_success_message_new_layer(aws_credentials, mock_function_config):
|
|
666
|
+
"""Test that the correct success message is shown when installing a layer on a function with no existing layers"""
|
|
667
|
+
|
|
668
|
+
mock_session = MagicMock()
|
|
669
|
+
mock_session.region_name = "us-east-1"
|
|
670
|
+
|
|
671
|
+
with patch(
|
|
672
|
+
"newrelic_lambda_cli.layers._get_license_key_outputs"
|
|
673
|
+
) as mock_get_license_key_outputs, patch(
|
|
674
|
+
"newrelic_lambda_cli.layers.success"
|
|
675
|
+
) as mock_success:
|
|
676
|
+
|
|
677
|
+
mock_get_license_key_outputs.return_value = ("license_arn", "12345", "policy")
|
|
678
|
+
mock_client = mock_session.client.return_value
|
|
638
679
|
|
|
639
|
-
|
|
680
|
+
config = mock_function_config("python3.12")
|
|
681
|
+
config["Configuration"]["Layers"] = []
|
|
682
|
+
mock_client.get_function.return_value = config
|
|
683
|
+
|
|
684
|
+
new_layer_arn = (
|
|
685
|
+
"arn:aws:lambda:us-east-1:451483290750:layer:NewRelicPython39:35"
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
with patch("newrelic_lambda_cli.layers._add_new_relic") as mock_add_new_relic:
|
|
689
|
+
mock_add_new_relic.return_value = {
|
|
690
|
+
"FunctionName": "test-function-name",
|
|
691
|
+
"Layers": [new_layer_arn],
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
function_arn = "test-function-arn"
|
|
695
|
+
result = install(
|
|
696
|
+
layer_install(nr_account_id=12345, session=mock_session), function_arn
|
|
697
|
+
)
|
|
698
|
+
|
|
699
|
+
assert result is True
|
|
700
|
+
|
|
701
|
+
mock_success.assert_called_once_with(
|
|
702
|
+
"Successfully installed Layer ARN %s for the function: %s"
|
|
703
|
+
% (new_layer_arn, function_arn)
|
|
704
|
+
)
|
|
@@ -21,6 +21,13 @@ def test_error():
|
|
|
21
21
|
def test_is_valid_handler():
|
|
22
22
|
assert is_valid_handler("fakeruntime", "not.a.valid.handler") is False
|
|
23
23
|
assert is_valid_handler("python3.9", "newrelic_lambda_wrapper.handler") is True
|
|
24
|
+
assert (
|
|
25
|
+
is_valid_handler(
|
|
26
|
+
"nodejs22",
|
|
27
|
+
"/opt/nodejs/node_modules/newrelic-esm-lambda-wrapper/index.handler",
|
|
28
|
+
)
|
|
29
|
+
is True
|
|
30
|
+
)
|
|
24
31
|
|
|
25
32
|
|
|
26
33
|
def test_parse_arn():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/decorators.py
RENAMED
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/functions.py
RENAMED
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/integrations.py
RENAMED
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/otel_ingestions.py
RENAMED
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/cli/subscriptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/otel_ingestions.py
RENAMED
|
File without changes
|
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli/subscriptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/requires.txt
RENAMED
|
File without changes
|
{newrelic_lambda_cli-0.9.6 → newrelic_lambda_cli-0.9.8}/newrelic_lambda_cli.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|