Skip to content

Commit

Permalink
feat: Adding Sync Warning (#3396)
Browse files Browse the repository at this point in the history
* Added Sync Confirmation Prompt

* Fixed Unit Tests

* Moved Warning Text to Constant
  • Loading branch information
CoshUS authored Oct 23, 2021
1 parent 9eb958f commit 2fe950f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
40 changes: 38 additions & 2 deletions samcli/commands/sync/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
DEFAULT_CACHE_DIR,
DEFAULT_BUILD_DIR_WITH_AUTO_DEPENDENCY_LAYER,
)
from samcli.commands._utils.experimental import ExperimentalFlag, force_experimental
from samcli.cli.cli_config_file import configuration_option, TomlProvider
from samcli.lib.utils.colors import Colored
from samcli.lib.utils.version_checker import check_newer_version
from samcli.lib.bootstrap.bootstrap import manage_stack
from samcli.lib.cli_validation.image_repository_validation import image_repository_validation
Expand All @@ -42,6 +42,11 @@
)
from samcli.cli.context import Context
from samcli.lib.sync.watch_manager import WatchManager
from samcli.commands._utils.experimental import (
ExperimentalFlag,
experimental,
is_experimental_enabled,
)

if TYPE_CHECKING: # pragma: no cover
from samcli.commands.deploy.deploy_context import DeployContext
Expand All @@ -55,6 +60,29 @@
By default, the sync command runs a full stack update, you can specify --code or --watch to which modes
"""

SYNC_CONFIRMATION_TEXT = """
The SAM CLI will use the AWS Lambda, Amazon API Gateway, and AWS StepFunctions APIs to upload your code without
performing a CloudFormation deployment. This will cause drift in your CloudFormation stack.
**The sync command should only be used against a development stack**.
Confirm that you are synchronizing a development stack.
Enter Y to proceed with the command, or enter N to cancel:
"""

SYNC_CONFIRMATION_TEXT_WITH_BETA = """
This feature is currently in beta. Visit the docs page to learn more about the AWS Beta terms https://aws.amazon.com/service-terms/.
The SAM CLI will use the AWS Lambda, Amazon API Gateway, and AWS StepFunctions APIs to upload your code without
performing a CloudFormation deployment. This will cause drift in your CloudFormation stack.
**The sync command should only be used against a development stack**.
Confirm that you are synchronizing a development stack and want to turn on beta features.
Enter Y to proceed with the command, or enter N to cancel:
"""


SHORT_HELP = "Sync a project to AWS"

DEFAULT_TEMPLATE_NAME = "template.yaml"
Expand Down Expand Up @@ -105,7 +133,7 @@
@notification_arns_option
@tags_option
@capabilities_option(default=DEFAULT_CAPABILITIES) # pylint: disable=E1120
@force_experimental(config_entry=ExperimentalFlag.Accelerate) # pylint: disable=E1120
@experimental
@pass_context
@track_command
@image_repository_validation
Expand Down Expand Up @@ -215,6 +243,14 @@ def do_cli(
build_dir = DEFAULT_BUILD_DIR_WITH_AUTO_DEPENDENCY_LAYER if dependency_layer else DEFAULT_BUILD_DIR
LOG.debug("Using build directory as %s", build_dir)

confirmation_text = SYNC_CONFIRMATION_TEXT

if not is_experimental_enabled(ExperimentalFlag.Accelerate):
confirmation_text = SYNC_CONFIRMATION_TEXT_WITH_BETA

if not click.confirm(Colored().yellow(confirmation_text), default=False):
return

with BuildContext(
resource_identifier=None,
template_file=template_file,
Expand Down
10 changes: 10 additions & 0 deletions samcli/lib/utils/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@
Wrapper to generated colored messages for printing in Terminal
"""

import platform
import os

import click

# Enables ANSI escape codes on Windows
if platform.system().lower() == "windows":
try:
os.system("color")
except Exception:
pass


class Colored:
"""
Expand Down
18 changes: 18 additions & 0 deletions tests/unit/commands/sync/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def setUp(self):
MOCK_SAM_CONFIG.reset_mock()

@parameterized.expand([(False, False, True), (False, False, False)])
@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.execute_code_sync")
@patch("samcli.commands.build.command.click")
@patch("samcli.commands.build.build_context.BuildContext")
Expand All @@ -70,6 +71,7 @@ def test_infra_must_succeed_sync(
BuildContextMock,
mock_build_click,
execute_code_sync_mock,
click_mock,
):

build_context_mock = Mock()
Expand Down Expand Up @@ -167,6 +169,7 @@ def test_infra_must_succeed_sync(
execute_code_sync_mock.assert_not_called()

@parameterized.expand([(False, True, False)])
@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.execute_watch")
@patch("samcli.commands.build.command.click")
@patch("samcli.commands.build.build_context.BuildContext")
Expand All @@ -190,6 +193,7 @@ def test_watch_must_succeed_sync(
BuildContextMock,
mock_build_click,
execute_watch_mock,
click_mock,
):

build_context_mock = Mock()
Expand Down Expand Up @@ -286,6 +290,7 @@ def test_watch_must_succeed_sync(
)

@parameterized.expand([(True, False, True)])
@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.execute_code_sync")
@patch("samcli.commands.build.command.click")
@patch("samcli.commands.build.build_context.BuildContext")
Expand All @@ -309,6 +314,7 @@ def test_code_must_succeed_sync(
BuildContextMock,
mock_build_click,
execute_code_sync_mock,
click_mock,
):

build_context_mock = Mock()
Expand Down Expand Up @@ -359,6 +365,7 @@ def setUp(self) -> None:
self.build_context = MagicMock()
self.deploy_context = MagicMock()

@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.SamLocalStackProvider.get_stacks")
@patch("samcli.commands.sync.command.SyncFlowFactory")
@patch("samcli.commands.sync.command.SyncFlowExecutor")
Expand All @@ -369,6 +376,7 @@ def test_execute_code_sync_single_resource(
sync_flow_executor_mock,
sync_flow_factory_mock,
get_stacks_mock,
click_mock,
):

resource_identifier_strings = ["Function1"]
Expand All @@ -395,6 +403,7 @@ def test_execute_code_sync_single_resource(
get_stacks_mock.return_value[0], resource_identifier_strings, []
)

@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.SamLocalStackProvider.get_stacks")
@patch("samcli.commands.sync.command.SyncFlowFactory")
@patch("samcli.commands.sync.command.SyncFlowExecutor")
Expand All @@ -405,6 +414,7 @@ def test_execute_code_sync_multiple_resource(
sync_flow_executor_mock,
sync_flow_factory_mock,
get_stacks_mock,
click_mock,
):

resource_identifier_strings = ["Function1", "Function2"]
Expand Down Expand Up @@ -438,6 +448,7 @@ def test_execute_code_sync_multiple_resource(
get_stacks_mock.return_value[0], resource_identifier_strings, []
)

@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.SamLocalStackProvider.get_stacks")
@patch("samcli.commands.sync.command.SyncFlowFactory")
@patch("samcli.commands.sync.command.SyncFlowExecutor")
Expand All @@ -448,6 +459,7 @@ def test_execute_code_sync_single_type_resource(
sync_flow_executor_mock,
sync_flow_factory_mock,
get_stacks_mock,
click_mock,
):

resource_identifier_strings = ["Function1", "Function2"]
Expand Down Expand Up @@ -484,6 +496,7 @@ def test_execute_code_sync_single_type_resource(
get_stacks_mock.return_value[0], resource_identifier_strings, ["Type1"]
)

@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.SamLocalStackProvider.get_stacks")
@patch("samcli.commands.sync.command.SyncFlowFactory")
@patch("samcli.commands.sync.command.SyncFlowExecutor")
Expand All @@ -494,6 +507,7 @@ def test_execute_code_sync_multiple_type_resource(
sync_flow_executor_mock,
sync_flow_factory_mock,
get_stacks_mock,
click_mock,
):
resource_identifier_strings = ["Function1", "Function2"]
resource_types = ["Type1", "Type2"]
Expand Down Expand Up @@ -533,6 +547,7 @@ def test_execute_code_sync_multiple_type_resource(
get_stacks_mock.return_value[0], resource_identifier_strings, ["Type1", "Type2"]
)

@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.SamLocalStackProvider.get_stacks")
@patch("samcli.commands.sync.command.SyncFlowFactory")
@patch("samcli.commands.sync.command.SyncFlowExecutor")
Expand All @@ -543,6 +558,7 @@ def test_execute_code_sync_default_all_resources(
sync_flow_executor_mock,
sync_flow_factory_mock,
get_stacks_mock,
click_mock,
):
sync_flows = [MagicMock(), MagicMock(), MagicMock(), MagicMock()]
sync_flow_factory_mock.return_value.create_sync_flow.side_effect = sync_flows
Expand Down Expand Up @@ -580,11 +596,13 @@ def setUp(self) -> None:
self.deploy_context = MagicMock()

@parameterized.expand([(True,), (False,)])
@patch("samcli.commands.sync.command.click")
@patch("samcli.commands.sync.command.WatchManager")
def test_execute_watch(
self,
auto_dependency_layer,
watch_manager_mock,
click_mock,
):
execute_watch(
self.template_file, self.build_context, self.package_context, self.deploy_context, auto_dependency_layer
Expand Down

0 comments on commit 2fe950f

Please sign in to comment.