|
2 | 2 | # (c) Copyright Instana Inc. 2020
|
3 | 3 |
|
4 | 4 | from __future__ import absolute_import
|
5 |
| -from io import BytesIO |
6 |
| -from zipfile import ZipFile |
7 | 5 | import unittest
|
8 | 6 | import json
|
9 | 7 |
|
10 | 8 | import boto3
|
11 |
| -import pytest |
12 |
| - |
13 | 9 | # TODO: Remove branching when we drop support for Python 3.7
|
14 |
| -import sys |
15 |
| -if sys.version_info >= (3, 8): |
| 10 | +from sys import version_info |
| 11 | +if version_info >= (3, 8): |
16 | 12 | from moto import mock_aws
|
17 | 13 | else:
|
18 | 14 | from moto import mock_lambda as mock_aws
|
19 | 15 |
|
20 |
| -from instana.singletons import tracer |
| 16 | +from instana.singletons import tracer, agent |
21 | 17 | from ...helpers import get_first_span_by_filter
|
22 | 18 |
|
| 19 | +@unittest.skip(version_info < (3, 8), "Test skipped on Python < 3.8") |
23 | 20 | class TestLambda(unittest.TestCase):
|
24 | 21 | def setUp(self):
|
25 | 22 | """ Clear all spans before a test run """
|
@@ -71,3 +68,190 @@ def test_lambda_invoke(self):
|
71 | 68 | self.assertEqual(boto_span.data['http']['status'], 200)
|
72 | 69 | self.assertEqual(boto_span.data['http']['method'], 'POST')
|
73 | 70 | self.assertEqual(boto_span.data['http']['url'], f'{endpoint}:443/Invoke')
|
| 71 | + |
| 72 | + |
| 73 | + def test_request_header_capture_before_call(self): |
| 74 | + original_extra_http_headers = agent.options.extra_http_headers |
| 75 | + agent.options.extra_http_headers = ['X-Capture-This', 'X-Capture-That'] |
| 76 | + |
| 77 | + # Access the event system on the S3 client |
| 78 | + event_system = self.aws_lambda.meta.events |
| 79 | + |
| 80 | + request_headers = { |
| 81 | + 'X-Capture-This': 'this', |
| 82 | + 'X-Capture-That': 'that' |
| 83 | + } |
| 84 | + |
| 85 | + # Create a function that adds custom headers |
| 86 | + def add_custom_header_before_call(params, **kwargs): |
| 87 | + params['headers'].update(request_headers) |
| 88 | + |
| 89 | + # Register the function to before-call event. |
| 90 | + event_system.register('before-call.lambda.Invoke', add_custom_header_before_call) |
| 91 | + |
| 92 | + with tracer.start_active_span('test'): |
| 93 | + result = self.aws_lambda.invoke(FunctionName=self.function_name, Payload=json.dumps({"message": "success"})) |
| 94 | + |
| 95 | + self.assertEqual(result["StatusCode"], 200) |
| 96 | + result_payload = json.loads(result["Payload"].read().decode("utf-8")) |
| 97 | + self.assertIn("message", result_payload) |
| 98 | + self.assertEqual("success", result_payload["message"]) |
| 99 | + |
| 100 | + spans = tracer.recorder.queued_spans() |
| 101 | + self.assertEqual(2, len(spans)) |
| 102 | + |
| 103 | + filter = lambda span: span.n == "sdk" |
| 104 | + test_span = get_first_span_by_filter(spans, filter) |
| 105 | + self.assertTrue(test_span) |
| 106 | + |
| 107 | + filter = lambda span: span.n == "boto3" |
| 108 | + boto_span = get_first_span_by_filter(spans, filter) |
| 109 | + self.assertTrue(boto_span) |
| 110 | + |
| 111 | + self.assertEqual(boto_span.t, test_span.t) |
| 112 | + self.assertEqual(boto_span.p, test_span.s) |
| 113 | + |
| 114 | + self.assertIsNone(test_span.ec) |
| 115 | + self.assertIsNone(boto_span.ec) |
| 116 | + |
| 117 | + self.assertEqual(boto_span.data['boto3']['op'], 'Invoke') |
| 118 | + endpoint = f'https://lambda.{self.lambda_region}.amazonaws.com' |
| 119 | + self.assertEqual(boto_span.data['boto3']['ep'], endpoint) |
| 120 | + self.assertEqual(boto_span.data['boto3']['reg'], self.lambda_region) |
| 121 | + self.assertIn('FunctionName', boto_span.data['boto3']['payload']) |
| 122 | + self.assertEqual(boto_span.data['boto3']['payload']['FunctionName'], self.function_name) |
| 123 | + self.assertEqual(boto_span.data['http']['status'], 200) |
| 124 | + self.assertEqual(boto_span.data['http']['method'], 'POST') |
| 125 | + self.assertEqual(boto_span.data['http']['url'], f'{endpoint}:443/Invoke') |
| 126 | + |
| 127 | + self.assertIn("X-Capture-This", boto_span.data["http"]["header"]) |
| 128 | + self.assertEqual("this", boto_span.data["http"]["header"]["X-Capture-This"]) |
| 129 | + self.assertIn("X-Capture-That", boto_span.data["http"]["header"]) |
| 130 | + self.assertEqual("that", boto_span.data["http"]["header"]["X-Capture-That"]) |
| 131 | + |
| 132 | + agent.options.extra_http_headers = original_extra_http_headers |
| 133 | + |
| 134 | + |
| 135 | + def test_request_header_capture_before_sign(self): |
| 136 | + original_extra_http_headers = agent.options.extra_http_headers |
| 137 | + agent.options.extra_http_headers = ['X-Custom-1', 'X-Custom-2'] |
| 138 | + |
| 139 | + # Access the event system on the S3 client |
| 140 | + event_system = self.aws_lambda.meta.events |
| 141 | + |
| 142 | + request_headers = { |
| 143 | + 'X-Custom-1': 'Value1', |
| 144 | + 'X-Custom-2': 'Value2' |
| 145 | + } |
| 146 | + |
| 147 | + # Create a function that adds custom headers |
| 148 | + def add_custom_header_before_sign(request, **kwargs): |
| 149 | + for name, value in request_headers.items(): |
| 150 | + request.headers.add_header(name, value) |
| 151 | + |
| 152 | + # Register the function to before-sign event. |
| 153 | + event_system.register_first('before-sign.lambda.Invoke', add_custom_header_before_sign) |
| 154 | + |
| 155 | + with tracer.start_active_span('test'): |
| 156 | + result = self.aws_lambda.invoke(FunctionName=self.function_name, Payload=json.dumps({"message": "success"})) |
| 157 | + |
| 158 | + self.assertEqual(result["StatusCode"], 200) |
| 159 | + result_payload = json.loads(result["Payload"].read().decode("utf-8")) |
| 160 | + self.assertIn("message", result_payload) |
| 161 | + self.assertEqual("success", result_payload["message"]) |
| 162 | + |
| 163 | + spans = tracer.recorder.queued_spans() |
| 164 | + self.assertEqual(2, len(spans)) |
| 165 | + |
| 166 | + filter = lambda span: span.n == "sdk" |
| 167 | + test_span = get_first_span_by_filter(spans, filter) |
| 168 | + self.assertTrue(test_span) |
| 169 | + |
| 170 | + filter = lambda span: span.n == "boto3" |
| 171 | + boto_span = get_first_span_by_filter(spans, filter) |
| 172 | + self.assertTrue(boto_span) |
| 173 | + |
| 174 | + self.assertEqual(boto_span.t, test_span.t) |
| 175 | + self.assertEqual(boto_span.p, test_span.s) |
| 176 | + |
| 177 | + self.assertIsNone(test_span.ec) |
| 178 | + self.assertIsNone(boto_span.ec) |
| 179 | + |
| 180 | + self.assertEqual(boto_span.data['boto3']['op'], 'Invoke') |
| 181 | + endpoint = f'https://lambda.{self.lambda_region}.amazonaws.com' |
| 182 | + self.assertEqual(boto_span.data['boto3']['ep'], endpoint) |
| 183 | + self.assertEqual(boto_span.data['boto3']['reg'], self.lambda_region) |
| 184 | + self.assertIn('FunctionName', boto_span.data['boto3']['payload']) |
| 185 | + self.assertEqual(boto_span.data['boto3']['payload']['FunctionName'], self.function_name) |
| 186 | + self.assertEqual(boto_span.data['http']['status'], 200) |
| 187 | + self.assertEqual(boto_span.data['http']['method'], 'POST') |
| 188 | + self.assertEqual(boto_span.data['http']['url'], f'{endpoint}:443/Invoke') |
| 189 | + |
| 190 | + self.assertIn("X-Custom-1", boto_span.data["http"]["header"]) |
| 191 | + self.assertEqual("Value1", boto_span.data["http"]["header"]["X-Custom-1"]) |
| 192 | + self.assertIn("X-Custom-2", boto_span.data["http"]["header"]) |
| 193 | + self.assertEqual("Value2", boto_span.data["http"]["header"]["X-Custom-2"]) |
| 194 | + |
| 195 | + agent.options.extra_http_headers = original_extra_http_headers |
| 196 | + |
| 197 | + |
| 198 | + def test_response_header_capture(self): |
| 199 | + original_extra_http_headers = agent.options.extra_http_headers |
| 200 | + agent.options.extra_http_headers = ['X-Capture-This-Too', 'X-Capture-That-Too'] |
| 201 | + |
| 202 | + # Access the event system on the S3 client |
| 203 | + event_system = self.aws_lambda.meta.events |
| 204 | + |
| 205 | + response_headers = { |
| 206 | + "X-Capture-This-Too": "this too", |
| 207 | + "X-Capture-That-Too": "that too", |
| 208 | + } |
| 209 | + |
| 210 | + # Create a function that sets the custom headers in the after-call event. |
| 211 | + def modify_after_call_args(parsed, **kwargs): |
| 212 | + parsed['ResponseMetadata']['HTTPHeaders'].update(response_headers) |
| 213 | + |
| 214 | + # Register the function to an event |
| 215 | + event_system.register('after-call.lambda.Invoke', modify_after_call_args) |
| 216 | + |
| 217 | + with tracer.start_active_span('test'): |
| 218 | + result = self.aws_lambda.invoke(FunctionName=self.function_name, Payload=json.dumps({"message": "success"})) |
| 219 | + |
| 220 | + self.assertEqual(result["StatusCode"], 200) |
| 221 | + result_payload = json.loads(result["Payload"].read().decode("utf-8")) |
| 222 | + self.assertIn("message", result_payload) |
| 223 | + self.assertEqual("success", result_payload["message"]) |
| 224 | + |
| 225 | + spans = tracer.recorder.queued_spans() |
| 226 | + self.assertEqual(2, len(spans)) |
| 227 | + |
| 228 | + filter = lambda span: span.n == "sdk" |
| 229 | + test_span = get_first_span_by_filter(spans, filter) |
| 230 | + self.assertTrue(test_span) |
| 231 | + |
| 232 | + filter = lambda span: span.n == "boto3" |
| 233 | + boto_span = get_first_span_by_filter(spans, filter) |
| 234 | + self.assertTrue(boto_span) |
| 235 | + |
| 236 | + self.assertEqual(boto_span.t, test_span.t) |
| 237 | + self.assertEqual(boto_span.p, test_span.s) |
| 238 | + |
| 239 | + self.assertIsNone(test_span.ec) |
| 240 | + self.assertIsNone(boto_span.ec) |
| 241 | + |
| 242 | + self.assertEqual(boto_span.data['boto3']['op'], 'Invoke') |
| 243 | + endpoint = f'https://lambda.{self.lambda_region}.amazonaws.com' |
| 244 | + self.assertEqual(boto_span.data['boto3']['ep'], endpoint) |
| 245 | + self.assertEqual(boto_span.data['boto3']['reg'], self.lambda_region) |
| 246 | + self.assertIn('FunctionName', boto_span.data['boto3']['payload']) |
| 247 | + self.assertEqual(boto_span.data['boto3']['payload']['FunctionName'], self.function_name) |
| 248 | + self.assertEqual(boto_span.data['http']['status'], 200) |
| 249 | + self.assertEqual(boto_span.data['http']['method'], 'POST') |
| 250 | + self.assertEqual(boto_span.data['http']['url'], f'{endpoint}:443/Invoke') |
| 251 | + |
| 252 | + self.assertIn("X-Capture-This-Too", boto_span.data["http"]["header"]) |
| 253 | + self.assertEqual("this too", boto_span.data["http"]["header"]["X-Capture-This-Too"]) |
| 254 | + self.assertIn("X-Capture-That-Too", boto_span.data["http"]["header"]) |
| 255 | + self.assertEqual("that too", boto_span.data["http"]["header"]["X-Capture-That-Too"]) |
| 256 | + |
| 257 | + agent.options.extra_http_headers = original_extra_http_headers |
0 commit comments