def test_destroy( self, async_used: bool, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test destroy.""" mock_async = MagicMock() mocker.patch.object(Deployment, "_Deployment__async", mock_async) mock_sync = MagicMock() mocker.patch.object(Deployment, "_Deployment__sync", mock_sync) runway_context._use_concurrent = async_used obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert obj.destroy() if async_used: mock_async.assert_called_once_with("destroy") mock_sync.assert_not_called() else: mock_async.assert_not_called() mock_sync.assert_called_once_with("destroy")
def test_deploy_async( self, caplog: LogCaptureFixture, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test deploy async.""" caplog.set_level(logging.INFO, logger="runway") mock_futures = mocker.patch(f"{MODULE}.concurrent.futures") executor = MagicMock() executor.__enter__.return_value = executor mock_futures.ProcessPoolExecutor.return_value = executor mocker.patch.object(Deployment, "use_async", True) mock_mp_context = mocker.patch("multiprocessing.get_context") obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert not obj.deploy() assert ( "unnamed_deployment:processing regions in parallel... (output will be interwoven)" in caplog.messages) mock_mp_context.assert_called_once_with("fork") mock_futures.ProcessPoolExecutor.assert_called_once_with( max_workers=runway_context.env.max_concurrent_regions, mp_context=mock_mp_context.return_value, ) executor.submit.assert_has_calls([ call(obj.run, "deploy", "us-east-1"), call(obj.run, "deploy", "us-west-2") ]) assert executor.submit.return_value.result.call_count == 2
def test_run( self, mock_module, mock_aws, fx_deployments, monkeypatch, runway_context ): """Test run.""" mock_resolve = MagicMock() mock_validate = MagicMock() definition = fx_deployments.load("min_required") monkeypatch.setattr(definition, "resolve", mock_resolve) monkeypatch.setattr(Deployment, "validate_account_credentials", mock_validate) obj = Deployment(context=runway_context, definition=definition) assert not obj.run("deploy", "us-west-2") assert runway_context.command == "deploy" assert runway_context.env.aws_region == "us-west-2" mock_resolve.assert_called_once_with(runway_context, obj._variables) mock_validate.assert_called_once_with(runway_context) mock_aws.AssumeRole.assert_called_once_with(runway_context) mock_aws.AssumeRole().__enter__.assert_called_once() mock_module.run_list.assert_called_once_with( action="deploy", context=runway_context, deployment=definition, future=obj._future, modules=definition.modules, variables=obj._variables, )
def test_init( self, async_used: bool, caplog: LogCaptureFixture, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test init.""" caplog.set_level(logging.INFO, logger="runway") mock_async = MagicMock() mocker.patch.object(Deployment, "_Deployment__async", mock_async) mock_sync = MagicMock() mocker.patch.object(Deployment, "_Deployment__sync", mock_sync) runway_context._use_concurrent = async_used obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert obj.init() if async_used: mock_async.assert_called_once_with("init") mock_sync.assert_not_called() else: mock_async.assert_not_called() mock_sync.assert_called_once_with("init")
def test_run( self, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test run.""" mock_aws = mocker.patch(f"{MODULE}.aws") mock_module = mocker.patch(f"{MODULE}.Module") definition = fx_deployments.load("min_required") mock_resolve = mocker.patch.object(definition, "resolve") mock_validate = mocker.patch.object(Deployment, "validate_account_credentials") obj = Deployment(context=runway_context, definition=definition) assert not obj.run("deploy", "us-west-2") assert runway_context.command == "deploy" assert runway_context.env.aws_region == "us-west-2" mock_resolve.assert_called_once_with(runway_context, variables=obj._variables) mock_validate.assert_called_once_with(runway_context) mock_aws.AssumeRole.assert_called_once_with(runway_context) mock_aws.AssumeRole().__enter__.assert_called_once() mock_module.run_list.assert_called_once_with( action="deploy", context=runway_context, deployment=definition, future=obj._future, modules=ANY, # list of module objects change variables=obj._variables, )
def test_plan( self, async_used: bool, caplog: LogCaptureFixture, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test plan.""" caplog.set_level(logging.INFO, logger="runway") mock_async = MagicMock() mocker.patch.object(Deployment, "_Deployment__async", mock_async) mock_sync = MagicMock() mocker.patch.object(Deployment, "_Deployment__sync", mock_sync) runway_context._use_concurrent = async_used obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert obj.plan() if async_used: assert ("unnamed_deployment:processing of regions will be done in " "parallel during deploy/destroy" in caplog.messages) mock_async.assert_not_called() mock_sync.assert_called_once_with("plan")
def test_deploy_async( self, mock_futures, caplog, fx_deployments, monkeypatch, runway_context ): """Test deploy async.""" caplog.set_level(logging.INFO, logger="runway") executor = MagicMock() mock_futures.ProcessPoolExecutor.return_value = executor monkeypatch.setattr(Deployment, "use_async", True) obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert not obj.deploy() assert ( "deployment_1:processing regions in parallel... (output will be interwoven)" in caplog.messages ) mock_futures.ProcessPoolExecutor.assert_called_once_with( max_workers=runway_context.env.max_concurrent_regions ) executor.submit.assert_has_calls( [call(obj.run, "deploy", "us-east-1"), call(obj.run, "deploy", "us-west-2")] ) mock_futures.wait.assert_called_once() assert executor.submit.return_value.result.call_count == 2
def test_run_async( self, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test run async.""" mocker.patch(f"{MODULE}.aws") # ensure that mock.MagicMock is used for backported features mock_module = mocker.patch(f"{MODULE}.Module", MagicMock()) definition = fx_deployments.load("simple_parallel_regions") runway_context._use_concurrent = True # ensure that mock.MagicMock is used for backported features mock_resolve = mocker.patch.object(definition, "resolve", MagicMock()) mocker.patch.object(Deployment, "validate_account_credentials") obj = Deployment(context=runway_context, definition=definition) assert not obj.run("destroy", "us-west-2") new_ctx = mock_resolve.call_args.args[0] assert new_ctx != runway_context assert new_ctx.command == "destroy" and runway_context.command != "destroy" assert (new_ctx.env.aws_region == "us-west-2" and runway_context.env.aws_region != "us-west-2") assert mock_module.run_list.call_args.kwargs["context"] == new_ctx
def test_deploy(self, fx_deployments, monkeypatch, runway_context): """Test deploy.""" mock_run = MagicMock() monkeypatch.setattr(Deployment, "run", mock_run) obj = Deployment( context=runway_context, definition=fx_deployments.load("min_required") ) assert not obj.deploy() mock_run.assert_called_once_with("deploy", "us-east-1")
def test_deploy( self, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test deploy.""" mock_run = MagicMock() mocker.patch.object(Deployment, "run", mock_run) obj = Deployment(context=runway_context, definition=fx_deployments.load("min_required")) assert not obj.deploy() mock_run.assert_called_once_with("deploy", "us-east-1")
def test_env_vars_config_unresolved( self, fx_deployments, monkeypatch, runway_context ): """Test env_vars_config unresolved.""" expected = {"key": "val"} monkeypatch.setattr( MODULE + ".merge_nested_environment_dicts", MagicMock(return_value=expected) ) monkeypatch.setattr( Deployment, "_Deployment__merge_env_vars", MagicMock(return_value=None) ) monkeypatch.setattr( DeploymentDefinition, "env_vars", PropertyMock( side_effect=[UnresolvedVariable("test", MagicMock()), expected] ), ) monkeypatch.setattr( DeploymentDefinition, "_env_vars", PropertyMock(), raising=False ) raw_deployment = fx_deployments.get("min_required") deployment = DeploymentDefinition.from_list([raw_deployment])[0] obj = Deployment(context=runway_context, definition=deployment) assert obj.env_vars_config == expected obj.definition._env_vars.resolve.assert_called_once()
def test_env_vars_config_unresolved( self, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test env_vars_config unresolved.""" expected = {"key": "val"} mocker.patch.object(Deployment, "_Deployment__merge_env_vars", MagicMock(return_value=None)) mocker.patch.object( RunwayDeploymentDefinition, "env_vars", PropertyMock(side_effect=[ UnresolvedVariable( Variable("test", "something", variable_type="runway"), MagicMock(), ), expected, ]), create=True, ) mocker.patch.object(RunwayDeploymentDefinition, "_env_vars", PropertyMock(), create=True) raw_deployment: Dict[str, Any] = cast(Dict[str, Any], fx_deployments.get("min_required")) deployment = RunwayDeploymentDefinition.parse_obj(raw_deployment) obj = Deployment(context=runway_context, definition=deployment) assert obj.env_vars_config == expected obj.definition._env_vars.resolve.assert_called_once()
def test_run_list(self, action, monkeypatch, runway_context): """Test run_list.""" dep0 = MagicMock() dep0.modules = ["module"] dep1 = MagicMock() dep1.modules = [] deployments = [dep0, dep1] mock_action = MagicMock() monkeypatch.setattr(Deployment, action, mock_action) mock_vars = MagicMock() assert not Deployment.run_list( action=action, context=runway_context, deployments=deployments, future=None, variables=mock_vars, ) dep0.resolve.assert_called_once_with( runway_context, variables=mock_vars, pre_process=True ) dep1.resolve.assert_called_once_with( runway_context, variables=mock_vars, pre_process=True ) mock_action.assert_called_once_with()
def test_deploy_sync(self, caplog, fx_deployments, monkeypatch, runway_context): """Test deploy sync.""" caplog.set_level(logging.INFO, logger="runway") mock_run = MagicMock() monkeypatch.setattr(Deployment, "use_async", False) monkeypatch.setattr(Deployment, "run", mock_run) obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert not obj.deploy() assert "deployment_1:processing regions sequentially..." in caplog.messages mock_run.assert_has_calls( [call("deploy", "us-east-1"), call("deploy", "us-west-2")] )
def test_use_async( self, config, use_concurrent, expected, fx_deployments, runway_context ): """Test use_async.""" runway_context._use_concurrent = use_concurrent obj = Deployment(context=runway_context, definition=fx_deployments.load(config)) assert obj.use_async == expected
def test_child_modules(self, fx_deployments: YamlLoaderDeployment, runway_context: MockRunwayContext) -> None: """Test child_modules.""" deployment = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_module"), ) mod0 = Module( context=runway_context, definition=deployment.definition.modules[0], deployment=deployment.definition, ) mod1 = Module( context=runway_context, definition=deployment.definition.modules[1], deployment=deployment.definition, ) assert len(mod0.child_modules) == 2 assert not mod1.child_modules for index, child in enumerate(mod0.child_modules): assert isinstance(child, Module) # basic checks to ensure the child was setup correctly assert child.ctx.env.name == runway_context.env.name assert child.definition.path == mod0.definition.child_modules[ index].path
def test_assume_role_config(self, config, expected, fx_deployments, runway_context): """Test assume_role_config.""" obj = Deployment(context=runway_context, definition=fx_deployments.load(config)) result = obj.assume_role_config assert {k: result[k] for k in sorted(result)} == { k: expected[k] for k in sorted(expected) }
def test_run_list( self, action: RunwayActionTypeDef, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test run_list.""" dep0 = MagicMock() dep0.modules = ["module"] dep1 = MagicMock() dep1.modules = [] deployments = [dep0, dep1] mock_action = MagicMock() mocker.patch.object(Deployment, action, mock_action) mock_vars = MagicMock() assert not Deployment.run_list( action=action, context=runway_context, deployments=deployments, # type: ignore future=None, # type: ignore variables=mock_vars, ) dep0.resolve.assert_called_once_with(runway_context, variables=mock_vars, pre_process=True) dep1.resolve.assert_called_once_with(runway_context, variables=mock_vars, pre_process=True) mock_action.assert_called_once_with()
def test_destroy(self, async_used, fx_deployments, monkeypatch, runway_context): """Test destroy.""" mock_async = MagicMock() monkeypatch.setattr(Deployment, "_Deployment__async", mock_async) mock_sync = MagicMock() monkeypatch.setattr(Deployment, "_Deployment__sync", mock_sync) runway_context._use_concurrent = async_used obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert obj.destroy() if async_used: mock_async.assert_called_once_with("destroy") mock_sync.assert_not_called() else: mock_async.assert_not_called() mock_sync.assert_called_once_with("destroy")
def test_assume_role_config( self, config: str, expected: Dict[str, Any], fx_deployments: YamlLoaderDeployment, runway_context: MockRunwayContext, ) -> None: """Test assume_role_config.""" obj = Deployment(context=runway_context, definition=fx_deployments.load(config)) assert obj.assume_role_config == expected
def test_regions( self, config: str, expected: List[str], fx_deployments: YamlLoaderDeployment, runway_context: MockRunwayContext, ) -> None: """Test regions.""" obj = Deployment(context=runway_context, definition=fx_deployments.load(config)) assert obj.regions == expected
def test_validate_account_credentials( self, caplog: LogCaptureFixture, mocker: MockerFixture, fx_deployments: YamlLoaderDeployment, runway_context: MockRunwayContext, ) -> None: """Test validate_account_credentials.""" caplog.set_level(logging.INFO, logger="runway") mock_aws = mocker.patch(f"{MODULE}.aws") obj = Deployment(context=runway_context, definition=fx_deployments.load("validate_account")) account = MagicMock() account.aliases = ["no-match"] account.id = "111111111111" mock_aws.AccountDetails.return_value = account with pytest.raises(SystemExit) as excinfo: assert obj.validate_account_credentials() assert excinfo.value.code == 1 assert 'does not match required account "123456789012"' in "\n".join( caplog.messages) caplog.clear() del excinfo account.id = "123456789012" with pytest.raises(SystemExit) as excinfo: assert obj.validate_account_credentials() assert excinfo.value.code == 1 logs = "\n".join(caplog.messages) assert "verified current AWS account matches required account id" in logs assert 'do not match required account alias "test"' in logs caplog.clear() del logs del excinfo account.aliases = ["test"] assert not obj.validate_account_credentials() logs = "\n".join(caplog.messages) assert "verified current AWS account matches required account id" in logs assert "verified current AWS account alias matches required alias" in logs
def test_run_async( self, mock_module, _mock_aws, fx_deployments, monkeypatch, runway_context ): """Test run async.""" mock_resolve = MagicMock() definition = fx_deployments.load("simple_parallel_regions") runway_context._use_concurrent = True monkeypatch.setattr(definition, "resolve", mock_resolve) monkeypatch.setattr(Deployment, "validate_account_credentials", MagicMock()) obj = Deployment(context=runway_context, definition=definition) assert not obj.run("destroy", "us-west-2") new_ctx = mock_resolve.call_args.args[0] assert new_ctx != runway_context assert new_ctx.command == "destroy" and runway_context.command != "destroy" assert ( new_ctx.env.aws_region == "us-west-2" and runway_context.env.aws_region != "us-west-2" ) assert mock_module.run_list.call_args.kwargs["context"] == new_ctx
def test_use_async( self, config: str, expected: bool, fx_deployments: YamlLoaderDeployment, runway_context: MockRunwayContext, use_concurrent: bool, ) -> None: """Test use_async.""" runway_context._use_concurrent = use_concurrent obj = Deployment(context=runway_context, definition=fx_deployments.load(config)) assert obj.use_async == expected
def test_init(self, fx_deployments, monkeypatch, runway_context): """Test init.""" definition = fx_deployments.load("min_required") mock_merge = MagicMock() monkeypatch.setattr(Deployment, "_Deployment__merge_env_vars", mock_merge) obj = Deployment(context=runway_context, definition=definition) assert isinstance(obj._future, FutureDefinition) assert isinstance(obj._variables, VariablesDefinition) assert obj.definition == definition assert obj.ctx == runway_context assert obj.name == "deployment_1" mock_merge.assert_called_once_with()
def test_plan( self, async_used, caplog, fx_deployments, monkeypatch, runway_context ): """Test plan.""" caplog.set_level(logging.INFO, logger="runway") mock_async = MagicMock() monkeypatch.setattr(Deployment, "_Deployment__async", mock_async) mock_sync = MagicMock() monkeypatch.setattr(Deployment, "_Deployment__sync", mock_sync) runway_context._use_concurrent = async_used obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert obj.plan() if async_used: assert ( "deployment_1:processing of regions will be done in " "parallel during deploy/destroy" in caplog.messages ) mock_async.assert_not_called() mock_sync.assert_called_once_with("plan")
def test_deploy_sync( self, caplog: LogCaptureFixture, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test deploy sync.""" caplog.set_level(logging.INFO, logger="runway") mock_run = MagicMock() mocker.patch.object(Deployment, "use_async", False) mocker.patch.object(Deployment, "run", mock_run) obj = Deployment( context=runway_context, definition=fx_deployments.load("simple_parallel_regions"), ) assert not obj.deploy() assert ("unnamed_deployment:processing regions sequentially..." in caplog.messages) mock_run.assert_has_calls( [call("deploy", "us-east-1"), call("deploy", "us-west-2")])
def test_init_args(self, fx_deployments, runway_context): """Test init with args.""" definition = fx_deployments.load("simple_env_vars_map") future = FutureDefinition(strict_environments=True) variables = VariablesDefinition(some_key="val") obj = Deployment( context=runway_context, definition=definition, future=future, variables=variables, ) assert obj._future == future assert obj._variables == variables assert obj.definition == definition assert obj.ctx == runway_context assert obj.name == "deployment_1" assert obj.ctx.env.vars["deployment_var"] == "val"
def test___init___args(self, fx_deployments: YamlLoaderDeployment, runway_context: MockRunwayContext) -> None: """Test __init__ with args.""" definition = fx_deployments.load("simple_env_vars") future = RunwayFutureDefinitionModel() variables = RunwayVariablesDefinition.parse_obj({"some_key": "val"}) obj = Deployment( context=runway_context, definition=definition, future=future, variables=variables, ) assert obj._future == future assert obj._variables == variables assert obj.definition == definition assert obj.ctx == runway_context assert obj.name == "unnamed_deployment" assert obj.ctx.env.vars["deployment_var"] == "val"
def test___init__( self, fx_deployments: YamlLoaderDeployment, mocker: MockerFixture, runway_context: MockRunwayContext, ) -> None: """Test __init__.""" definition = fx_deployments.load("min_required") mock_merge = MagicMock() mocker.patch.object(Deployment, "_Deployment__merge_env_vars", mock_merge) obj = Deployment(context=runway_context, definition=definition) assert isinstance(obj._future, RunwayFutureDefinitionModel) assert isinstance(obj._variables, RunwayVariablesDefinition) assert obj.definition == definition assert obj.ctx == runway_context assert obj.name == "unnamed_deployment" mock_merge.assert_called_once_with()