cloud-radar 0.13.3a16__tar.gz → 0.14.0a1__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 (18) hide show
  1. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/PKG-INFO +21 -4
  2. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/README.md +20 -3
  3. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/pyproject.toml +1 -1
  4. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/_template.py +17 -2
  5. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/functions.py +12 -1
  6. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/LICENSE.txt +0 -0
  7. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/__init__.py +0 -0
  8. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/__init__.py +0 -0
  9. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/e2e/__init__.py +0 -0
  10. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/e2e/_stack.py +0 -0
  11. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/__init__.py +0 -0
  12. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/_condition.py +0 -0
  13. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/_hooks.py +0 -0
  14. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/_output.py +0 -0
  15. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/_parameter.py +0 -0
  16. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/_resource.py +0 -0
  17. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/_stack.py +0 -0
  18. {cloud_radar-0.13.3a16 → cloud_radar-0.14.0a1}/src/cloud_radar/cf/unit/test__template.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloud-radar
3
- Version: 0.13.3a16
3
+ Version: 0.14.0a1
4
4
  Summary: Run functional tests on cloudformation stacks.
5
5
  Home-page: https://github.com/DontShaveTheYak/cloud-radar
6
6
  License: Apache-2.0
@@ -200,8 +200,8 @@ The default values for pseudo parameters:
200
200
  | **NoValue** | "" |
201
201
  | **Partition** | "aws" |
202
202
  | Region | "us-east-1" |
203
- | **StackId** | "" |
204
- | **StackName** | "" |
203
+ | StackId | (generated based on other values) |
204
+ | StackName | "my-cloud-radar-stack" |
205
205
  | **URLSuffix** | "amazonaws.com" |
206
206
  _Note: Bold variables are not fully implemented yet see the [Roadmap](#roadmap)_
207
207
 
@@ -242,6 +242,24 @@ dynamic_references = {
242
242
  template = Template(template_content, dynamic_references=dynamic_references)
243
243
  ```
244
244
 
245
+ There are cases where the default behaviour of our `GetAtt` implementation may not be sufficient and you need a more accurate returned value. When unit testing there are no real AWS resources created, and cloud-radar does not attempt to realistically generate attribute values - a string is always returned. This works good enough most of the time, but there are some cases where if you are attempting to apply intrinsic functions against the attribute value it needs to be more correct. When this occurs, you can add Metadata to the template to provide test values to use.
246
+
247
+ ```
248
+ Resources:
249
+ MediaPackageV2Channel:
250
+ Type: AWS::MediaPackageV2::Channel
251
+ Metadata:
252
+ Cloud-Radar:
253
+ attribute-values:
254
+ # Default behaviour of a string is not good enough here, the attribute value is expected to be a List.
255
+ IngestEndpointUrls:
256
+ - http://one.example.com
257
+ - http://two.example.com
258
+ Properties:
259
+ ChannelGroupName: dev_video_1
260
+ ChannelName: !Sub ${AWS::StackName}-MediaPackageChannel
261
+ ```
262
+
245
263
  A real unit testing example using Pytest can be seen [here](./tests/test_cf/test_examples/test_unit.py)
246
264
 
247
265
  </details>
@@ -338,7 +356,6 @@ A real functional testing example using Pytest can be seen [here](./tests/test_c
338
356
  ### Unit
339
357
  - Add full functionality to pseudo variables.
340
358
  * Variables like `Partition`, `URLSuffix` should change if the region changes.
341
- * Variables like `StackName` and `StackId` should have a better default than ""
342
359
  - Handle References to resources that shouldn't exist.
343
360
  * It's currently possible that a `!Ref` to a Resource stays in the final template even if that resource is later removed because of a conditional.
344
361
 
@@ -169,8 +169,8 @@ The default values for pseudo parameters:
169
169
  | **NoValue** | "" |
170
170
  | **Partition** | "aws" |
171
171
  | Region | "us-east-1" |
172
- | **StackId** | "" |
173
- | **StackName** | "" |
172
+ | StackId | (generated based on other values) |
173
+ | StackName | "my-cloud-radar-stack" |
174
174
  | **URLSuffix** | "amazonaws.com" |
175
175
  _Note: Bold variables are not fully implemented yet see the [Roadmap](#roadmap)_
176
176
 
@@ -211,6 +211,24 @@ dynamic_references = {
211
211
  template = Template(template_content, dynamic_references=dynamic_references)
212
212
  ```
213
213
 
214
+ There are cases where the default behaviour of our `GetAtt` implementation may not be sufficient and you need a more accurate returned value. When unit testing there are no real AWS resources created, and cloud-radar does not attempt to realistically generate attribute values - a string is always returned. This works good enough most of the time, but there are some cases where if you are attempting to apply intrinsic functions against the attribute value it needs to be more correct. When this occurs, you can add Metadata to the template to provide test values to use.
215
+
216
+ ```
217
+ Resources:
218
+ MediaPackageV2Channel:
219
+ Type: AWS::MediaPackageV2::Channel
220
+ Metadata:
221
+ Cloud-Radar:
222
+ attribute-values:
223
+ # Default behaviour of a string is not good enough here, the attribute value is expected to be a List.
224
+ IngestEndpointUrls:
225
+ - http://one.example.com
226
+ - http://two.example.com
227
+ Properties:
228
+ ChannelGroupName: dev_video_1
229
+ ChannelName: !Sub ${AWS::StackName}-MediaPackageChannel
230
+ ```
231
+
214
232
  A real unit testing example using Pytest can be seen [here](./tests/test_cf/test_examples/test_unit.py)
215
233
 
216
234
  </details>
@@ -307,7 +325,6 @@ A real functional testing example using Pytest can be seen [here](./tests/test_c
307
325
  ### Unit
308
326
  - Add full functionality to pseudo variables.
309
327
  * Variables like `Partition`, `URLSuffix` should change if the region changes.
310
- * Variables like `StackName` and `StackId` should have a better default than ""
311
328
  - Handle References to resources that shouldn't exist.
312
329
  * It's currently possible that a `!Ref` to a Resource stays in the final template even if that resource is later removed because of a conditional.
313
330
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "cloud-radar"
3
- version = "0.13.3a16"
3
+ version = "0.14.0a1"
4
4
  description = "Run functional tests on cloudformation stacks."
5
5
  readme = "README.md"
6
6
  authors = ["Levi Blaney <shadycuz@gmail.com>"]
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import json
4
4
  import re
5
+ import uuid
5
6
  from pathlib import Path
6
7
  from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, Union
7
8
 
@@ -26,8 +27,8 @@ class Template:
26
27
  NoValue: str = "" # Not yet implemented
27
28
  Partition: str = "aws" # Other regions not implemented
28
29
  Region: str = "us-east-1"
29
- StackId: str = "" # Not yet implemented
30
- StackName: str = "" # Not yet implemented
30
+ StackId: str = "" # If left blank this will be generated
31
+ StackName: str = "my-cloud-radar-stack"
31
32
  URLSuffix: str = "amazonaws.com" # Other regions not implemented
32
33
 
33
34
  def __init__(
@@ -310,6 +311,19 @@ class Template:
310
311
 
311
312
  return template
312
313
 
314
+ # If the StackId variable is not set, generate a value for it
315
+ def _get_populated_stack_id(self) -> str:
316
+ if not Template.StackId:
317
+ # Not explicitly set, generate a value
318
+ unique_uuid = uuid.uuid4()
319
+
320
+ return (
321
+ f"arn:{Template.Partition}:cloudformation:{self.Region}:"
322
+ f"{Template.AccountId}:stack/{Template.StackName}/{unique_uuid}"
323
+ )
324
+
325
+ return Template.StackId
326
+
313
327
  def create_stack(
314
328
  self,
315
329
  params: Optional[Dict[str, str]] = None,
@@ -318,6 +332,7 @@ class Template:
318
332
  ):
319
333
  if region:
320
334
  self.Region = region
335
+ self.StackId = self._get_populated_stack_id()
321
336
 
322
337
  self.render(params, parameters_file=parameters_file)
323
338
 
@@ -455,7 +455,18 @@ def get_att(template: "Template", values: Any) -> str:
455
455
  if resource_name not in template.template["Resources"]:
456
456
  raise KeyError(f"Fn::GetAtt - Resource {resource_name} not found in template.")
457
457
 
458
- return f"{resource_name}.{att_name}"
458
+ # Get the resource definition
459
+ resource = template.template["Resources"][resource_name]
460
+
461
+ # Check if there is a value in the resource Metadata for this attribute.
462
+ # If the attribute requested is in the metadata, return it.
463
+ # Otherwise use the string value of "{resource_name}.{att_name}"
464
+
465
+ metadata = resource.get("Metadata", {})
466
+ cloud_radar_metadata = metadata.get("Cloud-Radar", {})
467
+ attribute_values = cloud_radar_metadata.get("attribute-values", {})
468
+
469
+ return attribute_values.get(att_name, f"{resource_name}.{att_name}")
459
470
 
460
471
 
461
472
  def get_azs(_t: "Template", region: Any) -> List[str]: