Skip to content

Commit

Permalink
make future.strict_environments standard behavior (#586)
Browse files Browse the repository at this point in the history
* make `future.strict_environments` standard behavior

* update docs
  • Loading branch information
ITProKyle committed May 3, 2021
1 parent 8b98bdc commit 4d5b374
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 121 deletions.
18 changes: 18 additions & 0 deletions docs/source/runway_config.rst
Expand Up @@ -364,6 +364,13 @@ Deployment
environments:
dev: True
.. versionchanged:: 1.4.0
Now acts as an explicit toggle for deploying modules to a set AWS Account/AWS Region.
For passing values to a module, :attr:`deployment.parameters`/:attr:`module.parameters` should be used instead.

.. versionchanged:: 2.0.0
If defined and the current deploy environment is missing from the definition, processing will be skipped.

.. attribute:: modules
:type: List[Union[module, str]]

Expand Down Expand Up @@ -491,6 +498,8 @@ Deployment
dev:
namespace: example-dev
.. versionadded:: 1.4.0

.. attribute:: regions
:type: Optional[Union[Dict[str, Union[List[str], str], List[str], str]]
:value: []
Expand Down Expand Up @@ -677,6 +686,13 @@ Module
environments:
dev: True
.. versionchanged:: 1.4.0
Now acts as an explicit toggle for deploying modules to a set AWS Account/AWS Region.
For passing values to a module, :attr:`deployment.parameters`/:attr:`module.parameters` should be used instead.

.. versionchanged:: 2.0.0
If defined and the current deploy environment is missing from the definition, processing will be skipped.

.. attribute:: name
:type: Optional[str]

Expand Down Expand Up @@ -783,6 +799,8 @@ Module
dev:
namespace: example-dev
.. versionadded:: 1.4.0

.. attribute:: path
:type: Optional[Union[str, Path]]

Expand Down
6 changes: 0 additions & 6 deletions runway/config/models/runway/__init__.py
Expand Up @@ -349,12 +349,6 @@ def _validate_regions(cls, values: Dict[str, Any]) -> Dict[str, Any]: # noqa: N
class RunwayFutureDefinitionModel(ConfigProperty):
"""Model for the Runway future definition."""

strict_environments: bool = Field(
False,
description="If 'environments' is included in a deployment, modules will "
"be skipped if the current environment is not defined.",
)

class Config(ConfigProperty.Config):
"""Model configuration."""

Expand Down
24 changes: 4 additions & 20 deletions runway/core/components/_module.py
Expand Up @@ -94,12 +94,7 @@ def environment_matches_defined(self) -> Optional[bool]:
Will return None if there is nothing defined for the current environment.
"""
return validate_environment(
self.ctx,
self.environments,
logger=self.logger,
strict=self.__future.strict_environments,
)
return validate_environment(self.ctx, self.environments, logger=self.logger,)

@cached_property
def environments(self) -> RunwayEnvironmentsType:
Expand Down Expand Up @@ -331,16 +326,13 @@ def validate_environment(
context: RunwayContext,
env_def: Optional[Union[bool, Dict[str, Any], int, str, List[str]]],
logger: Union[PrefixAdaptor, RunwayLogger] = LOGGER,
strict: bool = False,
) -> Optional[bool]:
"""Check if an environment should be deployed to.
Args:
context: Runway context object.
env_def: Runway module definition.
logger: Logger to log messages to.
strict: Whether to consider the current environment missing from
definition as a failure.
Returns:
Booleon value of whether to deploy or not.
Expand All @@ -357,18 +349,10 @@ def validate_environment(
return cast(Optional[bool], env_def)
if isinstance(env_def, dict):
if context.env.name not in env_def:
if strict:
logger.info("skipped; environment not in definition")
return False
logger.info(
"environment not in definition; module will determine deployment"
)
return None
logger.info("skipped; environment not in definition")
return False
return validate_environment(
context,
cast(Any, env_def.get(context.env.name, False)),
logger=logger,
strict=strict,
context, cast(Any, env_def.get(context.env.name, False)), logger=logger,
)

account = aws.AccountDetails(context)
Expand Down
4 changes: 0 additions & 4 deletions tests/unit/config/models/runway/test_runway.py
Expand Up @@ -315,10 +315,6 @@ def test_extra(self) -> None:
assert errors[0]["loc"] == ("invalid",)
assert errors[0]["msg"] == "extra fields not permitted"

def test_field_defaults(self) -> None:
"""Test field defaults."""
assert not RunwayFutureDefinitionModel().strict_environments


class TestRunwayModuleDefinitionModel:
"""Test runway.config.models.runway.RunwayModuleDefinitionModel."""
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/core/components/test_deployment.py
Expand Up @@ -55,7 +55,7 @@ def test_init_args(
) -> None:
"""Test init with args."""
definition = fx_deployments.load("simple_env_vars")
future = RunwayFutureDefinitionModel(strict_environments=True)
future = RunwayFutureDefinitionModel()
variables = RunwayVariablesDefinition.parse_obj({"some_key": "val"})

obj = Deployment(
Expand Down
117 changes: 27 additions & 90 deletions tests/unit/core/components/test_module.py
Expand Up @@ -10,7 +10,6 @@
import yaml
from mock import MagicMock, call

from runway.config.models.runway import RunwayFutureDefinitionModel
from runway.core.components import Deployment, Module
from runway.core.components._module import validate_environment

Expand Down Expand Up @@ -94,7 +93,7 @@ def test_environment_matches_defined(
)
assert mod.environment_matches_defined == "success"
mock_validate_environment.assert_called_once_with(
mod.ctx, {"key": "val"}, logger=mod.logger, strict=False
mod.ctx, {"key": "val"}, logger=mod.logger
)

def test_environments_deployment(
Expand Down Expand Up @@ -231,22 +230,13 @@ def test_payload_with_opts_from_file(
assert result["parameters"] == opts["parameters"]

@pytest.mark.parametrize(
"strict, validate",
[
(False, None),
(True, False),
(False, None),
(True, False),
(False, None),
(True, False),
],
"validate", [None, False],
)
def test_should_skip(
self,
fx_deployments: YamlLoaderDeployment,
mocker: MockerFixture,
runway_context: MockRunwayContext,
strict: bool,
validate: Optional[bool],
) -> None:
"""Test should_skip."""
Expand All @@ -255,7 +245,6 @@ def test_should_skip(
mod = Module(
context=runway_context,
definition=fx_deployments.load("min_required").modules[0],
future=RunwayFutureDefinitionModel(strict_environments=strict),
)

result = mod.should_skip
Expand Down Expand Up @@ -556,102 +545,51 @@ def test_run_list(


@pytest.mark.parametrize(
"env_def, strict, expected, expected_logs",
"env_def, expected, expected_logs",
[
(
{"invalid"},
False,
False,
['skipped; unsupported type for environments "%s"' % type(set())], # type: ignore
),
(True, False, True, ["explicitly enabled"]),
(False, False, False, ["skipped; explicitly disabled"]),
(["123456789012/us-east-1"], False, True, []),
(
["123456789012/us-east-2"],
False,
False,
["skipped; account_id/region mismatch"],
),
("123456789012/us-east-1", False, True, []),
(
"123456789012/us-east-2",
False,
False,
["skipped; account_id/region mismatch"],
),
(
{},
False,
None,
["environment not defined; module will determine deployment"],
),
({}, True, None, ["environment not defined; module will determine deployment"]),
(True, True, ["explicitly enabled"]),
(False, False, ["skipped; explicitly disabled"]),
(["123456789012/us-east-1"], True, []),
(["123456789012/us-east-2"], False, ["skipped; account_id/region mismatch"],),
("123456789012/us-east-1", True, []),
("123456789012/us-east-2", False, ["skipped; account_id/region mismatch"],),
({}, None, ["environment not defined; module will determine deployment"],),
(
{"example": "111111111111/us-east-1"},
False,
None,
["environment not in definition; module will determine deployment"],
),
(
{"example": "111111111111/us-east-1"},
True,
False,
["skipped; environment not in definition"],
),
({"test": False}, False, False, ["skipped; explicitly disabled"]),
({"test": True}, False, True, ["explicitly enabled"]),
({"test": "123456789012/us-east-1"}, False, True, []),
({"test": False}, False, ["skipped; explicitly disabled"]),
({"test": True}, True, ["explicitly enabled"]),
({"test": "123456789012/us-east-1"}, True, []),
(
{"test": "123456789012/us-east-2"},
False,
False,
["skipped; account_id/region mismatch"],
),
({"test": "123456789012"}, False, True, []),
(
{"test": "111111111111"},
False,
False,
["skipped; account_id/region mismatch"],
),
({"test": 123456789012}, False, True, []),
({"test": 111111111111}, False, False, ["skipped; account_id/region mismatch"]),
({"test": "us-east-1"}, False, True, []),
({"test": "us-east-2"}, False, False, ["skipped; account_id/region mismatch"]),
(
{"test": ["123456789012/us-east-1", "123456789012/us-east-2"]},
False,
True,
[],
),
({"test": "123456789012"}, True, []),
({"test": "111111111111"}, False, ["skipped; account_id/region mismatch"],),
({"test": 123456789012}, True, []),
({"test": 111111111111}, False, ["skipped; account_id/region mismatch"]),
({"test": "us-east-1"}, True, []),
({"test": "us-east-2"}, False, ["skipped; account_id/region mismatch"]),
({"test": ["123456789012/us-east-1", "123456789012/us-east-2"]}, True, [],),
(
{"test": ["123456789012/us-east-2"]},
False,
False,
["skipped; account_id/region mismatch"],
),
({"test": ["123456789012", "111111111111"]}, False, True, []),
(
{"test": ["111111111111"]},
False,
False,
["skipped; account_id/region mismatch"],
),
({"test": [123456789012, 111111111111]}, False, True, []),
(
{"test": [111111111111]},
False,
False,
["skipped; account_id/region mismatch"],
),
({"test": ["us-east-1", "us-east-2"]}, False, True, []),
(
{"test": ["us-east-2"]},
False,
False,
["skipped; account_id/region mismatch"],
),
({"test": ["123456789012", "111111111111"]}, True, []),
({"test": ["111111111111"]}, False, ["skipped; account_id/region mismatch"],),
({"test": [123456789012, 111111111111]}, True, []),
({"test": [111111111111]}, False, ["skipped; account_id/region mismatch"],),
({"test": ["us-east-1", "us-east-2"]}, True, []),
({"test": ["us-east-2"]}, False, ["skipped; account_id/region mismatch"],),
],
)
def test_validate_environment(
Expand All @@ -661,15 +599,14 @@ def test_validate_environment(
expected: Optional[bool],
mocker: MockerFixture,
runway_context: MockRunwayContext,
strict: bool,
) -> None:
"""Test validate_environment."""
caplog.set_level(logging.DEBUG, logger="runway")
mocker.patch(
f"{MODULE}.aws",
**{"AccountDetails.return_value": MagicMock(id="123456789012")},
)
assert validate_environment(runway_context, env_def, strict=strict) is expected
assert validate_environment(runway_context, env_def) is expected
# all() does not give an output that can be used for troubleshooting failures
for log in expected_logs:
assert log in caplog.messages

0 comments on commit 4d5b374

Please sign in to comment.