|
3 | 3 | import json
|
4 | 4 | import os.path
|
5 | 5 | import re
|
| 6 | +import time |
6 | 7 | from functools import cmp_to_key, reduce
|
| 8 | +from pathlib import Path |
7 | 9 | from unittest import TestCase
|
8 | 10 | from unittest.mock import MagicMock, Mock, patch
|
9 | 11 |
|
|
21 | 23 | from tests.plugins.application.test_serverless_app_plugin import mock_get_region
|
22 | 24 | from tests.translator.helpers import get_template_parameter_values
|
23 | 25 |
|
| 26 | +PROJECT_ROOT = Path(__file__).parent.parent.parent |
24 | 27 | BASE_PATH = os.path.dirname(__file__)
|
25 | 28 | INPUT_FOLDER = BASE_PATH + "/input"
|
26 | 29 | OUTPUT_FOLDER = BASE_PATH + "/output"
|
|
37 | 40 | OUTPUT_FOLDER = os.path.join(BASE_PATH, "output")
|
38 | 41 |
|
39 | 42 |
|
| 43 | +def _parse_yaml(path): |
| 44 | + return yaml_parse(PROJECT_ROOT.joinpath(path).read_text()) |
| 45 | + |
| 46 | + |
40 | 47 | def deep_sort_lists(value):
|
41 | 48 | """
|
42 | 49 | Custom sorting implemented as a wrapper on top of Python's built-in ``sorted`` method. This is necessary because
|
@@ -657,6 +664,90 @@ def _do_transform(self, document, parameter_values=get_template_parameter_values
|
657 | 664 | return output_fragment
|
658 | 665 |
|
659 | 666 |
|
| 667 | +class TestApiAlwaysDeploy(TestCase): |
| 668 | + """ |
| 669 | + AlwaysDeploy is used to force API Gateway to redeploy at every deployment. |
| 670 | + See https://github.com/aws/serverless-application-model/issues/660 |
| 671 | +
|
| 672 | + Since it relies on the system time to generate the template, need to patch |
| 673 | + time.time() for deterministic tests. |
| 674 | + """ |
| 675 | + |
| 676 | + @staticmethod |
| 677 | + def get_deployment_ids(template): |
| 678 | + cfn_template = Translator({}, Parser()).translate(template, {}) |
| 679 | + deployment_ids = set() |
| 680 | + for k, v in cfn_template["Resources"].items(): |
| 681 | + if v["Type"] == "AWS::ApiGateway::Deployment": |
| 682 | + deployment_ids.add(k) |
| 683 | + return deployment_ids |
| 684 | + |
| 685 | + @patch("boto3.session.Session.region_name", "ap-southeast-1") |
| 686 | + @patch("botocore.client.ClientEndpointBridge._check_default_region", mock_get_region) |
| 687 | + def test_always_deploy(self): |
| 688 | + with patch("time.time", lambda: 13.37): |
| 689 | + obj = _parse_yaml("tests/translator/input/translate_always_deploy.yaml") |
| 690 | + deployment_ids = TestApiAlwaysDeploy.get_deployment_ids(obj) |
| 691 | + self.assertEqual(deployment_ids, {"MyApiDeploymentbd307a3ec3"}) |
| 692 | + |
| 693 | + with patch("time.time", lambda: 42.123): |
| 694 | + obj = _parse_yaml("tests/translator/input/translate_always_deploy.yaml") |
| 695 | + deployment_ids = TestApiAlwaysDeploy.get_deployment_ids(obj) |
| 696 | + self.assertEqual(deployment_ids, {"MyApiDeployment92cfceb39d"}) |
| 697 | + |
| 698 | + with patch("time.time", lambda: 42.1337): |
| 699 | + obj = _parse_yaml("tests/translator/input/translate_always_deploy.yaml") |
| 700 | + deployment_ids = TestApiAlwaysDeploy.get_deployment_ids(obj) |
| 701 | + self.assertEqual(deployment_ids, {"MyApiDeployment92cfceb39d"}) |
| 702 | + |
| 703 | + @patch("boto3.session.Session.region_name", "ap-southeast-1") |
| 704 | + @patch("botocore.client.ClientEndpointBridge._check_default_region", mock_get_region) |
| 705 | + def test_without_alwaysdeploy_never_changes(self): |
| 706 | + sam_template = { |
| 707 | + "Resources": { |
| 708 | + "MyApi": { |
| 709 | + "Type": "AWS::Serverless::Api", |
| 710 | + "Properties": { |
| 711 | + "StageName": "prod", |
| 712 | + }, |
| 713 | + } |
| 714 | + }, |
| 715 | + } |
| 716 | + |
| 717 | + deployment_ids = set() |
| 718 | + deployment_ids.update(TestApiAlwaysDeploy.get_deployment_ids(sam_template)) |
| 719 | + time.sleep(2) |
| 720 | + deployment_ids.update(TestApiAlwaysDeploy.get_deployment_ids(sam_template)) |
| 721 | + time.sleep(2) |
| 722 | + deployment_ids.update(TestApiAlwaysDeploy.get_deployment_ids(sam_template)) |
| 723 | + |
| 724 | + self.assertEqual(len(deployment_ids), 1) |
| 725 | + |
| 726 | + @patch("boto3.session.Session.region_name", "ap-southeast-1") |
| 727 | + @patch("botocore.client.ClientEndpointBridge._check_default_region", mock_get_region) |
| 728 | + def test_with_alwaysdeploy_always_changes(self): |
| 729 | + sam_template = { |
| 730 | + "Resources": { |
| 731 | + "MyApi": { |
| 732 | + "Type": "AWS::Serverless::Api", |
| 733 | + "Properties": { |
| 734 | + "StageName": "prod", |
| 735 | + "AlwaysDeploy": True, |
| 736 | + }, |
| 737 | + } |
| 738 | + }, |
| 739 | + } |
| 740 | + |
| 741 | + deployment_ids = set() |
| 742 | + deployment_ids.update(TestApiAlwaysDeploy.get_deployment_ids(sam_template)) |
| 743 | + time.sleep(2) |
| 744 | + deployment_ids.update(TestApiAlwaysDeploy.get_deployment_ids(sam_template)) |
| 745 | + time.sleep(2) |
| 746 | + deployment_ids.update(TestApiAlwaysDeploy.get_deployment_ids(sam_template)) |
| 747 | + |
| 748 | + self.assertEqual(len(deployment_ids), 3) |
| 749 | + |
| 750 | + |
660 | 751 | class TestTemplateValidation(TestCase):
|
661 | 752 | _MANAGED_POLICIES_TEMPLATE = {
|
662 | 753 | "Resources": {
|
|
0 commit comments