newrelic-lambda-cli 0.9.7__tar.gz → 0.9.9__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.
Files changed (46) hide show
  1. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/PKG-INFO +10 -26
  2. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/README.md +9 -25
  3. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/cli/layers.py +5 -0
  4. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/layers.py +41 -2
  5. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/types.py +1 -0
  6. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/utils.py +6 -0
  7. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli.egg-info/PKG-INFO +10 -26
  8. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/setup.py +1 -1
  9. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/tests/test_layers.py +147 -3
  10. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/tests/test_utils.py +7 -0
  11. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/CODE_OF_CONDUCT.md +0 -0
  12. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/CONTRIBUTING.md +0 -0
  13. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/LICENSE +0 -0
  14. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/MANIFEST.in +0 -0
  15. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/THIRD_PARTY_NOTICES.md +0 -0
  16. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/__init__.py +0 -0
  17. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/api.py +0 -0
  18. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/cli/__init__.py +0 -0
  19. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/cli/decorators.py +0 -0
  20. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/cli/functions.py +0 -0
  21. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/cli/integrations.py +0 -0
  22. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/cli/otel_ingestions.py +0 -0
  23. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/cli/subscriptions.py +0 -0
  24. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/cliutils.py +0 -0
  25. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/functions.py +0 -0
  26. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/integrations.py +0 -0
  27. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/otel_ingestions.py +0 -0
  28. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/permissions.py +0 -0
  29. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/subscriptions.py +0 -0
  30. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/templates/import-template.yaml +0 -0
  31. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/templates/license-key-secret.yaml +0 -0
  32. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli/templates/nr-lambda-integration-role.yaml +0 -0
  33. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli.egg-info/SOURCES.txt +0 -0
  34. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli.egg-info/dependency_links.txt +0 -0
  35. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli.egg-info/entry_points.txt +0 -0
  36. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli.egg-info/not-zip-safe +0 -0
  37. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli.egg-info/requires.txt +0 -0
  38. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/newrelic_lambda_cli.egg-info/top_level.txt +0 -0
  39. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/pyproject.toml +0 -0
  40. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/setup.cfg +0 -0
  41. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/tests/test_api.py +0 -0
  42. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/tests/test_functions.py +0 -0
  43. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/tests/test_integrations.py +0 -0
  44. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/tests/test_new_relic_gql.py +0 -0
  45. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/tests/test_permissions.py +0 -0
  46. {newrelic_lambda_cli-0.9.7 → newrelic_lambda_cli-0.9.9}/tests/test_subscriptions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: newrelic-lambda-cli
3
- Version: 0.9.7
3
+ Version: 0.9.9
4
4
  Summary: A CLI to install the New Relic AWS Lambda integration and layers.
5
5
  Home-page: https://github.com/newrelic/newrelic-lambda-cli
6
6
  Author: New Relic
@@ -62,37 +62,21 @@ A CLI to install the New Relic AWS Lambda integration and layers.
62
62
 
63
63
  ## Runtimes Supported
64
64
 
65
- * dotnetcore3.1
66
- * dotnet6
67
- * dotnet8
68
- * java8.al2
69
- * java11
70
- * java17
71
- * java21
72
- * nodejs16.x
73
- * nodejs18.x
74
- * nodejs20.x
75
- * nodejs22.x
76
- * provided
77
- * provided.al2
78
- * provided.al2023
79
- * python3.7
80
- * python3.8
81
- * python3.9
82
- * python3.10
83
- * python3.11
84
- * python3.12
85
- * python3.13
86
- * ruby3.2
87
- * ruby3.3
88
- * ruby3.4
65
+ | Runtime | Versions |
66
+ |-------------|------------------------|
67
+ | Python | `python3.7`, `python3.8`, `python3.9`, `python3.10`, `python3.11`, `python3.12`, `python3.13` |
68
+ | Node.js | `nodejs16.x`, `nodejs18.x`, `nodejs20.x`, `nodejs22.x` |
69
+ | .NET | `dotnet3.1`, `dotnet6`, `dotnet8` |
70
+ | Java | `java8.al2`, `java11`, `java17`, `java21` |
71
+ | Provided | `provided`, `provided.al2`, `provided.al2023` |
72
+ | Ruby | `ruby3.2`, `ruby3.3`, `ruby3.4` |
89
73
 
90
74
  **Note:** Automatic handler wrapping is only supported for Node.js, Python, Java, and Ruby. For other runtimes,
91
75
  manual function wrapping is required using the runtime specific New Relic agent.
92
76
 
93
77
  ## Requirements
94
78
 
95
- * Python >= 3.3 <= 3.12
79
+ * Python >= 3.7 <= 3.13
96
80
  * Retrieve your [New relic Account ID](https://docs.newrelic.com/docs/accounts/install-new-relic/account-setup/account-id) and [User API Key](https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys#user-api-key)
97
81
 
98
82
  ## Recommendations
@@ -36,37 +36,21 @@ A CLI to install the New Relic AWS Lambda integration and layers.
36
36
 
37
37
  ## Runtimes Supported
38
38
 
39
- * dotnetcore3.1
40
- * dotnet6
41
- * dotnet8
42
- * java8.al2
43
- * java11
44
- * java17
45
- * java21
46
- * nodejs16.x
47
- * nodejs18.x
48
- * nodejs20.x
49
- * nodejs22.x
50
- * provided
51
- * provided.al2
52
- * provided.al2023
53
- * python3.7
54
- * python3.8
55
- * python3.9
56
- * python3.10
57
- * python3.11
58
- * python3.12
59
- * python3.13
60
- * ruby3.2
61
- * ruby3.3
62
- * ruby3.4
39
+ | Runtime | Versions |
40
+ |-------------|------------------------|
41
+ | Python | `python3.7`, `python3.8`, `python3.9`, `python3.10`, `python3.11`, `python3.12`, `python3.13` |
42
+ | Node.js | `nodejs16.x`, `nodejs18.x`, `nodejs20.x`, `nodejs22.x` |
43
+ | .NET | `dotnet3.1`, `dotnet6`, `dotnet8` |
44
+ | Java | `java8.al2`, `java11`, `java17`, `java21` |
45
+ | Provided | `provided`, `provided.al2`, `provided.al2023` |
46
+ | Ruby | `ruby3.2`, `ruby3.3`, `ruby3.4` |
63
47
 
64
48
  **Note:** Automatic handler wrapping is only supported for Node.js, Python, Java, and Ruby. For other runtimes,
65
49
  manual function wrapping is required using the runtime specific New Relic agent.
66
50
 
67
51
  ## Requirements
68
52
 
69
- * Python >= 3.3 <= 3.12
53
+ * Python >= 3.7 <= 3.13
70
54
  * Retrieve your [New relic Account ID](https://docs.newrelic.com/docs/accounts/install-new-relic/account-setup/account-id) and [User API Key](https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys#user-api-key)
71
55
 
72
56
  ## Recommendations
@@ -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",
@@ -24,6 +24,7 @@ NEW_RELIC_ENV_VARS = (
24
24
  "NEW_RELIC_LICENSE_KEY",
25
25
  "NEW_RELIC_LOG_ENDPOINT",
26
26
  "NEW_RELIC_TELEMETRY_ENDPOINT",
27
+ "NEW_RELIC_APM_LAMBDA_MODE",
27
28
  )
28
29
 
29
30
 
@@ -118,6 +119,7 @@ def _add_new_relic(input, config, nr_license_key):
118
119
  success(
119
120
  "Already installed on function '%s'. Pass --upgrade (or -u) to allow "
120
121
  "upgrade or reinstall to latest layer version."
122
+ "Additionally pass --apm to enable APM Lambda mode."
121
123
  % config["Configuration"]["FunctionArn"]
122
124
  )
123
125
  return True
@@ -232,6 +234,13 @@ def _add_new_relic(input, config, nr_license_key):
232
234
  "CORECLR_PROFILER_PATH"
233
235
  ] = "/opt/lib/newrelic-dotnet-agent/libNewRelicProfiler.so"
234
236
 
237
+ if input.apm:
238
+ success(
239
+ "Enabling APM Lambda mode for function '%s' "
240
+ % config["Configuration"]["FunctionArn"]
241
+ )
242
+ update_kwargs["Environment"]["Variables"]["NEW_RELIC_APM_LAMBDA_MODE"] = "True"
243
+
235
244
  return update_kwargs
236
245
 
237
246
 
@@ -295,6 +304,14 @@ def install(input, function_arn):
295
304
 
296
305
  try:
297
306
  res = client.update_function_configuration(**update_kwargs)
307
+ if input.apm:
308
+ client.tag_resource(
309
+ Resource=config["Configuration"]["FunctionArn"],
310
+ Tags={
311
+ "NR.Apm.Lambda.Mode": "true",
312
+ },
313
+ )
314
+ success("Successfully added APM tag to the function")
298
315
  except botocore.exceptions.ClientError as e:
299
316
  failure(
300
317
  "Failed to update configuration for '%s': %s"
@@ -313,7 +330,25 @@ def install(input, function_arn):
313
330
  if input.verbose:
314
331
  click.echo(json.dumps(res, indent=2))
315
332
 
316
- success("Successfully installed layer on %s" % function_arn)
333
+ old_layers = config["Configuration"].get("Layers", [])
334
+ old_layer_arn = old_layers[0]["Arn"].rsplit(":", 1)[0] if old_layers else "None"
335
+ old_layer_version = (
336
+ old_layers[0]["Arn"].split(":")[-1] if old_layers else "None"
337
+ )
338
+ new_layer = update_kwargs["Layers"][0]
339
+ new_layer_arn = update_kwargs["Layers"][0].rsplit(":", 1)[0]
340
+ new_layer_version = update_kwargs["Layers"][0].split(":")[-1]
341
+
342
+ if old_layer_arn == "None":
343
+ success(
344
+ "Successfully installed Layer ARN %s for the function: %s"
345
+ % (new_layer, function_arn)
346
+ )
347
+ else:
348
+ success(
349
+ "Successfully upgraded Layer ARN %s from version: %s to version: %s for the function: %s"
350
+ % (new_layer_arn, old_layer_version, new_layer_version, function_arn)
351
+ )
317
352
  return True
318
353
 
319
354
 
@@ -412,7 +447,11 @@ def uninstall(input, function_arn):
412
447
  if input.verbose:
413
448
  click.echo(json.dumps(res, indent=2))
414
449
 
415
- success("Successfully uninstalled layer on %s" % function_arn)
450
+ old_layers = config["Configuration"].get("Layers", [])
451
+ old_layer_arn = old_layers[0]["Arn"] if old_layers else "None"
452
+ success(
453
+ "Successfully uninstalled Layer %s from %s" % (old_layer_arn, function_arn)
454
+ )
416
455
  return True
417
456
 
418
457
 
@@ -104,6 +104,7 @@ LAYER_INSTALL_KEYS = [
104
104
  "excludes",
105
105
  "layer_arn",
106
106
  "upgrade",
107
+ "apm",
107
108
  "enable_extension",
108
109
  "enable_extension_function_logs",
109
110
  "java_handler_method",
@@ -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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: newrelic-lambda-cli
3
- Version: 0.9.7
3
+ Version: 0.9.9
4
4
  Summary: A CLI to install the New Relic AWS Lambda integration and layers.
5
5
  Home-page: https://github.com/newrelic/newrelic-lambda-cli
6
6
  Author: New Relic
@@ -62,37 +62,21 @@ A CLI to install the New Relic AWS Lambda integration and layers.
62
62
 
63
63
  ## Runtimes Supported
64
64
 
65
- * dotnetcore3.1
66
- * dotnet6
67
- * dotnet8
68
- * java8.al2
69
- * java11
70
- * java17
71
- * java21
72
- * nodejs16.x
73
- * nodejs18.x
74
- * nodejs20.x
75
- * nodejs22.x
76
- * provided
77
- * provided.al2
78
- * provided.al2023
79
- * python3.7
80
- * python3.8
81
- * python3.9
82
- * python3.10
83
- * python3.11
84
- * python3.12
85
- * python3.13
86
- * ruby3.2
87
- * ruby3.3
88
- * ruby3.4
65
+ | Runtime | Versions |
66
+ |-------------|------------------------|
67
+ | Python | `python3.7`, `python3.8`, `python3.9`, `python3.10`, `python3.11`, `python3.12`, `python3.13` |
68
+ | Node.js | `nodejs16.x`, `nodejs18.x`, `nodejs20.x`, `nodejs22.x` |
69
+ | .NET | `dotnet3.1`, `dotnet6`, `dotnet8` |
70
+ | Java | `java8.al2`, `java11`, `java17`, `java21` |
71
+ | Provided | `provided`, `provided.al2`, `provided.al2023` |
72
+ | Ruby | `ruby3.2`, `ruby3.3`, `ruby3.4` |
89
73
 
90
74
  **Note:** Automatic handler wrapping is only supported for Node.js, Python, Java, and Ruby. For other runtimes,
91
75
  manual function wrapping is required using the runtime specific New Relic agent.
92
76
 
93
77
  ## Requirements
94
78
 
95
- * Python >= 3.3 <= 3.12
79
+ * Python >= 3.7 <= 3.13
96
80
  * Retrieve your [New relic Account ID](https://docs.newrelic.com/docs/accounts/install-new-relic/account-setup/account-id) and [User API Key](https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys#user-api-key)
97
81
 
98
82
  ## Recommendations
@@ -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.7",
9
+ version="0.9.9",
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,113 @@ 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
+
266
+ def test_install_apm(aws_credentials, mock_function_config):
267
+ mock_session = MagicMock()
268
+ mock_session.region_name = "us-east-1"
269
+ expected_tags_after_tagging = {
270
+ "NR.Apm.Lambda.Mode": "true",
271
+ }
272
+
273
+ with patch(
274
+ "newrelic_lambda_cli.layers._get_license_key_outputs"
275
+ ) as mock_get_license_key_outputs:
276
+ mock_client = mock_session.client.return_value
277
+
278
+ mock_client.get_function.reset_mock(return_value=True)
279
+
280
+ config = mock_function_config("python3.12")
281
+ mock_client.get_function.return_value = config
282
+
283
+ mock_get_license_key_outputs.return_value = ("license_arn", "12345", "policy")
284
+
285
+ try:
286
+ install(
287
+ layer_install(
288
+ session=mock_session,
289
+ aws_region="us-east-1",
290
+ nr_account_id=12345,
291
+ apm=True,
292
+ ),
293
+ "APMLambda",
294
+ )
295
+ except UsageError as e:
296
+ print(f"UsageError: {e}")
297
+
298
+ mock_client.get_function.reset_mock()
299
+ config = mock_function_config("python3.12")
300
+ mock_client.get_function.return_value = config
301
+ mock_client.list_tags.return_value = {"Tags": expected_tags_after_tagging}
302
+ assert (
303
+ install(
304
+ layer_install(nr_account_id=12345, session=mock_session), "APMLambda"
305
+ )
306
+ is True
307
+ )
308
+
309
+ mock_client.assert_has_calls([call.get_function(FunctionName="APMLambda")])
310
+ mock_client.assert_has_calls(
311
+ [
312
+ call.update_function_configuration(
313
+ FunctionName="arn:aws:lambda:us-east-1:5558675309:function:aws-python3-dev-hello", # noqa
314
+ Environment={
315
+ "Variables": {
316
+ "EXISTING_ENV_VAR": "Hello World",
317
+ "NEW_RELIC_ACCOUNT_ID": "12345",
318
+ "NEW_RELIC_LAMBDA_HANDLER": "original_handler",
319
+ "NEW_RELIC_LAMBDA_EXTENSION_ENABLED": "false",
320
+ "NEW_RELIC_APM_LAMBDA_MODE": "True",
321
+ }
322
+ },
323
+ Layers=ANY,
324
+ Handler="newrelic_lambda_wrapper.handler",
325
+ )
326
+ ]
327
+ )
328
+
329
+ mock_client.assert_has_calls(
330
+ [
331
+ call.tag_resource(
332
+ Resource="arn:aws:lambda:us-east-1:5558675309:function:aws-python3-dev-hello",
333
+ Tags={
334
+ "NR.Apm.Lambda.Mode": "true",
335
+ },
336
+ )
337
+ ]
338
+ )
339
+
340
+ tags_from_list_tags = mock_client.list_tags(Resource="APMLambda")["Tags"]
341
+
342
+ assert tags_from_list_tags == expected_tags_after_tagging
343
+
344
+
238
345
  @mock_aws
239
346
  def test_add_new_relic_dotnet(aws_credentials, mock_function_config):
240
347
  session = boto3.Session(region_name="us-east-1")
@@ -633,7 +740,44 @@ def test_uninstall(aws_credentials, mock_function_config):
633
740
  )
634
741
 
635
742
 
636
- def test_layers_index():
637
- layers = index("ap-southeast-1", "nodejs20.x", "x86_64")
743
+ @mock_aws
744
+ def test_install_success_message_new_layer(aws_credentials, mock_function_config):
745
+ """Test that the correct success message is shown when installing a layer on a function with no existing layers"""
746
+
747
+ mock_session = MagicMock()
748
+ mock_session.region_name = "us-east-1"
749
+
750
+ with patch(
751
+ "newrelic_lambda_cli.layers._get_license_key_outputs"
752
+ ) as mock_get_license_key_outputs, patch(
753
+ "newrelic_lambda_cli.layers.success"
754
+ ) as mock_success:
755
+
756
+ mock_get_license_key_outputs.return_value = ("license_arn", "12345", "policy")
757
+ mock_client = mock_session.client.return_value
758
+
759
+ config = mock_function_config("python3.12")
760
+ config["Configuration"]["Layers"] = []
761
+ mock_client.get_function.return_value = config
762
+
763
+ new_layer_arn = (
764
+ "arn:aws:lambda:us-east-1:451483290750:layer:NewRelicPython39:35"
765
+ )
638
766
 
639
- assert len(layers) == 1
767
+ with patch("newrelic_lambda_cli.layers._add_new_relic") as mock_add_new_relic:
768
+ mock_add_new_relic.return_value = {
769
+ "FunctionName": "test-function-name",
770
+ "Layers": [new_layer_arn],
771
+ }
772
+
773
+ function_arn = "test-function-arn"
774
+ result = install(
775
+ layer_install(nr_account_id=12345, session=mock_session), function_arn
776
+ )
777
+
778
+ assert result is True
779
+
780
+ mock_success.assert_called_once_with(
781
+ "Successfully installed Layer ARN %s for the function: %s"
782
+ % (new_layer_arn, function_arn)
783
+ )
@@ -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():