def test_structured_events(self): project_name = "structured_events" stack_name = stack_namer(project_name) stack = create_stack(stack_name, program=pulumi_program, project_name=project_name) stack_config: ConfigMap = { "bar": ConfigValue(value="abc"), "buzz": ConfigValue(value="secret", secret=True) } try: stack.set_all_config(stack_config) # can't mutate a bool from the callback, so use a single-item list seen_summary_event = [False] def find_summary_event(event: EngineEvent): if event.summary_event: seen_summary_event[0] = True # pulumi up up_res = stack.up(on_event=find_summary_event) self.assertEqual(seen_summary_event[0], True, "No SummaryEvent for `up`") self.assertEqual(up_res.summary.kind, "update") self.assertEqual(up_res.summary.result, "succeeded") # pulumi preview seen_summary_event[0] = False pre_res = stack.preview(on_event=find_summary_event) self.assertEqual(seen_summary_event[0], True, "No SummaryEvent for `preview`") self.assertEqual(pre_res.change_summary.get(OpType.SAME), 1) # pulumi refresh seen_summary_event[0] = False refresh_res = stack.refresh(on_event=find_summary_event) self.assertEqual(seen_summary_event[0], True, "No SummaryEvent for `refresh`") self.assertEqual(refresh_res.summary.kind, "refresh") self.assertEqual(refresh_res.summary.result, "succeeded") # pulumi destroy seen_summary_event[0] = False destroy_res = stack.destroy(on_event=find_summary_event) self.assertEqual(seen_summary_event[0], True, "No SummaryEvent for `destroy`") self.assertEqual(destroy_res.summary.kind, "destroy") self.assertEqual(destroy_res.summary.result, "succeeded") finally: stack.workspace.remove_stack(stack_name)
def test_config_flag_like(self): project_name = "python_test" project_settings = ProjectSettings(project_name, runtime="python") ws = LocalWorkspace(project_settings=project_settings) stack_name = stack_namer(project_name) stack = Stack.create(stack_name, ws) stack.set_config("key", ConfigValue(value="-value")) stack.set_config("secret-key", ConfigValue(value="-value", secret=True)) all_config = stack.get_all_config() self.assertFalse(all_config["python_test:key"].secret) self.assertEqual(all_config["python_test:key"].value, "-value") self.assertTrue(all_config["python_test:secret-key"].secret) self.assertEqual(all_config["python_test:secret-key"].value, "-value") ws.remove_stack(stack_name)
def test_supports_stack_outputs(self): project_name = "inline_python" stack_name = stack_namer(project_name) stack = create_stack(stack_name, program=pulumi_program, project_name=project_name) stack_config: ConfigMap = { "bar": ConfigValue(value="abc"), "buzz": ConfigValue(value="secret", secret=True) } def assert_outputs(outputs): self.assertEqual(len(outputs), 3) self.assertEqual(outputs["exp_static"].value, "foo") self.assertFalse(outputs["exp_static"].secret) self.assertEqual(outputs["exp_cfg"].value, "abc") self.assertFalse(outputs["exp_cfg"].secret) self.assertEqual(outputs["exp_secret"].value, "secret") self.assertTrue(outputs["exp_secret"].secret) try: stack.set_all_config(stack_config) initial_outputs = stack.outputs() self.assertEqual(len(initial_outputs), 0) # pulumi up up_res = stack.up() self.assertEqual(up_res.summary.kind, "update") self.assertEqual(up_res.summary.result, "succeeded") assert_outputs(up_res.outputs) outputs_after_up = stack.outputs() assert_outputs(outputs_after_up) # pulumi destroy destroy_res = stack.destroy() self.assertEqual(destroy_res.summary.kind, "destroy") self.assertEqual(destroy_res.summary.result, "succeeded") outputs_after_destroy = stack.outputs() self.assertEqual(len(outputs_after_destroy), 0) finally: stack.workspace.remove_stack(stack_name)
def test_stack_lifecycle_inline_program(self): project_name = "inline_python" stack_name = stack_namer(project_name) stack = create_stack(stack_name, program=pulumi_program, project_name=project_name) stack_config: ConfigMap = { "bar": ConfigValue(value="abc"), "buzz": ConfigValue(value="secret", secret=True) } try: stack.set_all_config(stack_config) # pulumi up up_res = stack.up() self.assertEqual(len(up_res.outputs), 3) self.assertEqual(up_res.outputs["exp_static"].value, "foo") self.assertFalse(up_res.outputs["exp_static"].secret) self.assertEqual(up_res.outputs["exp_cfg"].value, "abc") self.assertFalse(up_res.outputs["exp_cfg"].secret) self.assertEqual(up_res.outputs["exp_secret"].value, "secret") self.assertTrue(up_res.outputs["exp_secret"].secret) self.assertEqual(up_res.summary.kind, "update") self.assertEqual(up_res.summary.result, "succeeded") # pulumi preview preview_result = stack.preview() self.assertEqual(preview_result.change_summary.get(OpType.SAME), 1) # pulumi refresh refresh_res = stack.refresh() self.assertEqual(refresh_res.summary.kind, "refresh") self.assertEqual(refresh_res.summary.result, "succeeded") # pulumi destroy destroy_res = stack.destroy() self.assertEqual(destroy_res.summary.kind, "destroy") self.assertEqual(destroy_res.summary.result, "succeeded") finally: stack.workspace.remove_stack(stack_name)
def test_stack_lifecycle_local_program(self): project_name = "testproj" stack_name = stack_namer(project_name) work_dir = test_path("data", project_name) stack = create_stack(stack_name, work_dir=work_dir) self.assertIsNone(print(stack)) config: ConfigMap = { "bar": ConfigValue(value="abc"), "buzz": ConfigValue(value="secret", secret=True) } stack.set_all_config(config) # pulumi up up_res = stack.up() self.assertEqual(len(up_res.outputs), 3) self.assertEqual(up_res.outputs["exp_static"].value, "foo") self.assertFalse(up_res.outputs["exp_static"].secret) self.assertEqual(up_res.outputs["exp_cfg"].value, "abc") self.assertFalse(up_res.outputs["exp_cfg"].secret) self.assertEqual(up_res.outputs["exp_secret"].value, "secret") self.assertTrue(up_res.outputs["exp_secret"].secret) self.assertEqual(up_res.summary.kind, "update") self.assertEqual(up_res.summary.result, "succeeded") # pulumi preview preview_result = stack.preview() self.assertEqual(preview_result.change_summary.get(OpType.SAME), 1) # pulumi refresh refresh_res = stack.refresh() self.assertEqual(refresh_res.summary.kind, "refresh") self.assertEqual(refresh_res.summary.result, "succeeded") # pulumi destroy destroy_res = stack.destroy() self.assertEqual(destroy_res.summary.kind, "destroy") self.assertEqual(destroy_res.summary.result, "succeeded") stack.workspace.remove_stack(stack_name)
def test_bulk_config_ops(self): project_name = "python_test" project_settings = ProjectSettings(project_name, runtime="python") ws = LocalWorkspace(project_settings=project_settings) stack_name = stack_namer(project_name) stack = Stack.create(stack_name, ws) config: ConfigMap = { "one": ConfigValue(value="one"), "two": ConfigValue(value="two"), "three": ConfigValue(value="three", secret=True), "four": ConfigValue(value="four", secret=True), "five": ConfigValue(value="five"), "six": ConfigValue(value="six"), "seven": ConfigValue(value="seven", secret=True), "eight": ConfigValue(value="eight", secret=True), "nine": ConfigValue(value="nine"), "ten": ConfigValue(value="ten"), } stack.set_all_config(config) stack.remove_all_config([key for key in config]) ws.remove_stack(stack_name)
def test_config_functions(self): project_name = "python_test" project_settings = ProjectSettings(project_name, runtime="python") ws = LocalWorkspace(project_settings=project_settings) stack_name = stack_namer(project_name) stack = Stack.create(stack_name, ws) config: ConfigMap = { "plain": ConfigValue(value="abc"), "secret": ConfigValue(value="def", secret=True) } plain_key = normalize_config_key("plain", project_name) secret_key = normalize_config_key("secret", project_name) self.assertRaises(CommandError, stack.get_config, plain_key) values = stack.get_all_config() self.assertEqual(len(values), 0) stack.set_all_config(config) values = stack.get_all_config() self.assertEqual(values[plain_key].value, "abc") self.assertFalse(values[plain_key].secret) self.assertEqual(values[secret_key].value, "def") self.assertTrue(values[secret_key].secret) stack.remove_config("plain") values = stack.get_all_config() self.assertEqual(len(values), 1) stack.set_config("foo", ConfigValue(value="bar")) values = stack.get_all_config() self.assertEqual(len(values), 2) ws.remove_stack(stack_name)
def test_secret_config_warnings(self): def program(): config = Config() config.get("plainstr1") config.require("plainstr2") config.get_secret("plainstr3") config.require_secret("plainstr4") config.get_bool("plainbool1") config.require_bool("plainbool2") config.get_secret_bool("plainbool3") config.require_secret_bool("plainbool4") config.get_int("plainint1") config.require_int("plainint2") config.get_secret_int("plainint3") config.require_secret_int("plainint4") config.get_float("plainfloat1") config.require_float("plainfloat2") config.get_secret_float("plainfloat3") config.require_secret_float("plainfloat4") config.get_object("plainobj1") config.require_object("plainobj2") config.get_secret_object("plainobj3") config.require_secret_object("plainobj4") config.get("str1") config.require("str2") config.get_secret("str3") config.require_secret("str4") config.get_bool("bool1") config.require_bool("bool2") config.get_secret_bool("bool3") config.require_secret_bool("bool4") config.get_int("int1") config.require_int("int2") config.get_secret_int("int3") config.require_secret_int("int4") config.get_float("float1") config.require_float("float2") config.get_secret_float("float3") config.require_secret_float("float4") config.get_object("obj1") config.require_object("obj2") config.get_secret_object("obj3") config.require_secret_object("obj4") project_name = "inline_python" stack_name = stack_namer(project_name) stack = create_stack(stack_name, program=program, project_name=project_name) stack_config: ConfigMap = { "plainstr1": ConfigValue(value="1"), "plainstr2": ConfigValue(value="2"), "plainstr3": ConfigValue(value="3"), "plainstr4": ConfigValue(value="4"), "plainbool1": ConfigValue(value="true"), "plainbool2": ConfigValue(value="true"), "plainbool3": ConfigValue(value="true"), "plainbool4": ConfigValue(value="true"), "plainint1": ConfigValue(value="1"), "plainint2": ConfigValue(value="2"), "plainint3": ConfigValue(value="3"), "plainint4": ConfigValue(value="4"), "plainfloat1": ConfigValue(value="1.1"), "plainfloat2": ConfigValue(value="2.2"), "plainfloat3": ConfigValue(value="3.3"), "plainfloat4": ConfigValue(value="4.3"), "plainobj1": ConfigValue(value="{}"), "plainobj2": ConfigValue(value="{}"), "plainobj3": ConfigValue(value="{}"), "plainobj4": ConfigValue(value="{}"), "str1": ConfigValue(value="1", secret=True), "str2": ConfigValue(value="2", secret=True), "str3": ConfigValue(value="3", secret=True), "str4": ConfigValue(value="4", secret=True), "bool1": ConfigValue(value="true", secret=True), "bool2": ConfigValue(value="true", secret=True), "bool3": ConfigValue(value="true", secret=True), "bool4": ConfigValue(value="true", secret=True), "int1": ConfigValue(value="1", secret=True), "int2": ConfigValue(value="2", secret=True), "int3": ConfigValue(value="3", secret=True), "int4": ConfigValue(value="4", secret=True), "float1": ConfigValue(value="1.1", secret=True), "float2": ConfigValue(value="2.2", secret=True), "float3": ConfigValue(value="3.3", secret=True), "float4": ConfigValue(value="4.4", secret=True), "obj1": ConfigValue(value="{}", secret=True), "obj2": ConfigValue(value="{}", secret=True), "obj3": ConfigValue(value="{}", secret=True), "obj4": ConfigValue(value="{}", secret=True), } try: stack.set_all_config(stack_config) events: List[str] = [] def find_diagnostic_events(event: EngineEvent): if event.diagnostic_event and event.diagnostic_event.severity == "warning": events.append(event.diagnostic_event.message) expected_warnings = [ "Configuration 'inline_python:str1' value is a secret; use `get_secret` instead of `get`", "Configuration 'inline_python:str2' value is a secret; use `require_secret` instead of `require`", "Configuration 'inline_python:bool1' value is a secret; use `get_secret_bool` instead of `get_bool`", "Configuration 'inline_python:bool2' value is a secret; use `require_secret_bool` instead of `require_bool`", "Configuration 'inline_python:int1' value is a secret; use `get_secret_int` instead of `get_int`", "Configuration 'inline_python:int2' value is a secret; use `require_secret_int` instead of `require_int`", "Configuration 'inline_python:float1' value is a secret; use `get_secret_float` instead of `get_float`", "Configuration 'inline_python:float2' value is a secret; use `require_secret_float` instead of `require_float`", "Configuration 'inline_python:obj1' value is a secret; use `get_secret_object` instead of `get_object`", "Configuration 'inline_python:obj2' value is a secret; use `require_secret_object` instead of `require_object`", ] # These keys should not be in any warning messages. unexpected_warnings = [ "plainstr1", "plainstr2", "plainstr3", "plainstr4", "plainbool1", "plainbool2", "plainbool3", "plainbool4", "plainint1", "plainint2", "plainint3", "plainint4", "plainfloat1", "plainfloat2", "plainfloat3", "plainfloat4", "plainobj1", "plainobj2", "plainobj3", "plainobj4", "str3", "str4", "bool3", "bool4", "int3", "int4", "float3", "float4", "obj3", "obj4", ] def validate(warnings: List[str]): for expected in expected_warnings: found = False for warning in warnings: if expected in warning: found = True break self.assertTrue(found, "expected warning not found") for unexpected in unexpected_warnings: for warning in warnings: self.assertFalse( unexpected in warning, f"Unexpected ${unexpected}' found in warning") # pulumi preview stack.preview(on_event=find_diagnostic_events) validate(events) # pulumi up events = [] stack.up(on_event=find_diagnostic_events) validate(events) finally: stack.workspace.remove_stack(stack_name)