From a6b6437b493bde032eda9f7a3acb704f42625d6c Mon Sep 17 00:00:00 2001 From: Komal Date: Wed, 17 Feb 2021 10:16:35 -0800 Subject: [PATCH] [Automation] Fix python nested config parsing (#6349) --- CHANGELOG.md | 3 ++ sdk/go/x/auto/local_workspace_test.go | 45 +++++++++++++++++++ .../x/auto/test/nested_config/Pulumi.dev.yaml | 12 +++++ sdk/go/x/auto/test/nested_config/Pulumi.yaml | 3 ++ .../data/nested_config/Pulumi.dev.yaml | 12 +++++ .../automation/data/nested_config/Pulumi.yaml | 3 ++ .../tests/automation/localWorkspace.spec.ts | 28 ++++++++++-- .../pulumi/x/automation/_local_workspace.py | 5 ++- .../data/nested_config/Pulumi.dev.yaml | 12 +++++ .../automation/data/nested_config/Pulumi.yaml | 3 ++ .../test/automation/test_local_workspace.py | 26 ++++++++++- 11 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 sdk/go/x/auto/test/nested_config/Pulumi.dev.yaml create mode 100644 sdk/go/x/auto/test/nested_config/Pulumi.yaml create mode 100644 sdk/nodejs/tests/automation/data/nested_config/Pulumi.dev.yaml create mode 100644 sdk/nodejs/tests/automation/data/nested_config/Pulumi.yaml create mode 100644 sdk/python/lib/test/automation/data/nested_config/Pulumi.dev.yaml create mode 100644 sdk/python/lib/test/automation/data/nested_config/Pulumi.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 191525dbc..f286ae342 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,9 @@ CHANGELOG - [sdk/python] Define `__all__` in modules for better IDE autocomplete. [#6351](https://github.com/pulumi/pulumi/pull/6351) +- [automation/python] Fix a bug in nested configuration parsing. + [#6349](https://github.com/pulumi/pulumi/pull/6349) + ## 2.20.0 (2021-02-03) - [sdk/python] Fix `Output.from_input` to unwrap nested output values in input types (args classes), which addresses diff --git a/sdk/go/x/auto/local_workspace_test.go b/sdk/go/x/auto/local_workspace_test.go index 93f98e6b0..46b69c752 100644 --- a/sdk/go/x/auto/local_workspace_test.go +++ b/sdk/go/x/auto/local_workspace_test.go @@ -1087,6 +1087,51 @@ func TestImportExportStack(t *testing.T) { assert.Equal(t, "succeeded", dRes.Summary.Result) } +func TestNestedConfig(t *testing.T) { + ctx := context.Background() + stackName := FullyQualifiedStackName(pulumiOrg, "nested_config", "dev") + + // initialize + pDir := filepath.Join(".", "test", "nested_config") + s, err := UpsertStackLocalSource(ctx, stackName, pDir) + if err != nil { + t.Errorf("failed to initialize stack, err: %v", err) + t.FailNow() + } + + allConfig, err := s.GetAllConfig(ctx) + if err != nil { + t.Errorf("failed to get config, err: %v", err) + t.FailNow() + } + + outerVal, ok := allConfig["nested_config:outer"] + assert.True(t, ok) + assert.True(t, outerVal.Secret) + assert.JSONEq(t, "{\"inner\":\"my_secret\", \"other\": \"something_else\"}", outerVal.Value) + + listVal, ok := allConfig["nested_config:myList"] + assert.True(t, ok) + assert.False(t, listVal.Secret) + assert.JSONEq(t, "[\"one\",\"two\",\"three\"]", listVal.Value) + + outer, err := s.GetConfig(ctx, "outer") + if err != nil { + t.Errorf("failed to get config, err: %v", err) + t.FailNow() + } + assert.True(t, outer.Secret) + assert.JSONEq(t, "{\"inner\":\"my_secret\", \"other\": \"something_else\"}", outer.Value) + + list, err := s.GetConfig(ctx, "myList") + if err != nil { + t.Errorf("failed to get config, err: %v", err) + t.FailNow() + } + assert.False(t, list.Secret) + assert.JSONEq(t, "[\"one\",\"two\",\"three\"]", list.Value) +} + func getTestOrg() string { testOrg := "pulumi-test" if _, set := os.LookupEnv("PULUMI_TEST_ORG"); set { diff --git a/sdk/go/x/auto/test/nested_config/Pulumi.dev.yaml b/sdk/go/x/auto/test/nested_config/Pulumi.dev.yaml new file mode 100644 index 000000000..048673b5c --- /dev/null +++ b/sdk/go/x/auto/test/nested_config/Pulumi.dev.yaml @@ -0,0 +1,12 @@ +config: + aws:region: us-west-2 + nested_config:bar: 1234 + nested_config:foo: aha + nested_config:myList: + - one + - two + - three + nested_config:outer: + inner: + secure: AAABADOd8UPayqGlunla+Lo6kSSYA4LffCNBe84ElLwv0kyz7oIcYAw= + other: something_else diff --git a/sdk/go/x/auto/test/nested_config/Pulumi.yaml b/sdk/go/x/auto/test/nested_config/Pulumi.yaml new file mode 100644 index 000000000..80a948624 --- /dev/null +++ b/sdk/go/x/auto/test/nested_config/Pulumi.yaml @@ -0,0 +1,3 @@ +name: nested_config +runtime: go +description: A minimal Go Pulumi program diff --git a/sdk/nodejs/tests/automation/data/nested_config/Pulumi.dev.yaml b/sdk/nodejs/tests/automation/data/nested_config/Pulumi.dev.yaml new file mode 100644 index 000000000..048673b5c --- /dev/null +++ b/sdk/nodejs/tests/automation/data/nested_config/Pulumi.dev.yaml @@ -0,0 +1,12 @@ +config: + aws:region: us-west-2 + nested_config:bar: 1234 + nested_config:foo: aha + nested_config:myList: + - one + - two + - three + nested_config:outer: + inner: + secure: AAABADOd8UPayqGlunla+Lo6kSSYA4LffCNBe84ElLwv0kyz7oIcYAw= + other: something_else diff --git a/sdk/nodejs/tests/automation/data/nested_config/Pulumi.yaml b/sdk/nodejs/tests/automation/data/nested_config/Pulumi.yaml new file mode 100644 index 000000000..80a948624 --- /dev/null +++ b/sdk/nodejs/tests/automation/data/nested_config/Pulumi.yaml @@ -0,0 +1,3 @@ +name: nested_config +runtime: go +description: A minimal Go Pulumi program diff --git a/sdk/nodejs/tests/automation/localWorkspace.spec.ts b/sdk/nodejs/tests/automation/localWorkspace.spec.ts index a0c515997..0f708beb2 100644 --- a/sdk/nodejs/tests/automation/localWorkspace.spec.ts +++ b/sdk/nodejs/tests/automation/localWorkspace.spec.ts @@ -16,7 +16,7 @@ import * as assert from "assert"; import * as upath from "upath"; import { Config } from "../../index"; -import { ConfigMap, LocalWorkspace, ProjectSettings, Stack } from "../../x/automation"; +import { ConfigMap, fullyQualifiedStackName, LocalWorkspace, ProjectSettings, Stack } from "../../x/automation"; import { asyncTest } from "../util"; describe("LocalWorkspace", () => { @@ -116,6 +116,28 @@ describe("LocalWorkspace", () => { await ws.removeStack(stackName); })); + it(`nested_config`, asyncTest(async () => { + const stackName = fullyQualifiedStackName("pulumi-test", "nested_config", "dev"); + const workDir = upath.joinSafe(__dirname, "data", "nested_config"); + const stack = await LocalWorkspace.createOrSelectStack({ stackName, workDir }); + + const allConfig = await stack.getAllConfig(); + const outerVal = allConfig["nested_config:outer"]; + assert.strictEqual(outerVal.secret, true); + assert.strictEqual(outerVal.value, "{\"inner\":\"my_secret\",\"other\":\"something_else\"}"); + + const listVal = allConfig["nested_config:myList"]; + assert.strictEqual(listVal.secret, false); + assert.strictEqual(listVal.value, "[\"one\",\"two\",\"three\"]"); + + const outer = await stack.getConfig("outer"); + assert.strictEqual(outer.secret, true); + assert.strictEqual(outer.value, "{\"inner\":\"my_secret\",\"other\":\"something_else\"}"); + + const list = await stack.getConfig("myList"); + assert.strictEqual(list.secret, false); + assert.strictEqual(list.value, "[\"one\",\"two\",\"three\"]"); + })); it(`can list stacks and currently selected stack`, asyncTest(async () => { const projectSettings: ProjectSettings = { name: `node_list_test${getTestSuffix()}`, @@ -281,8 +303,8 @@ describe("LocalWorkspace", () => { const projectName = "inline_node"; const stack = await LocalWorkspace.createStack({ stackName, projectName, program }); - // pulumi up - await assert.rejects(stack.up()) + // pulumi up + await assert.rejects(stack.up()); // pulumi destroy const destroyRes = await stack.destroy(); diff --git a/sdk/python/lib/pulumi/x/automation/_local_workspace.py b/sdk/python/lib/pulumi/x/automation/_local_workspace.py index ad89969e3..04759e85c 100644 --- a/sdk/python/lib/pulumi/x/automation/_local_workspace.py +++ b/sdk/python/lib/pulumi/x/automation/_local_workspace.py @@ -152,7 +152,7 @@ class LocalWorkspace(Workspace): self.select_stack(stack_name) result = self._run_pulumi_cmd_sync(["config", "get", key, "--json"]) val = json.loads(result.stdout) - return ConfigValue(**val) + return ConfigValue(value=val["value"], secret=val["secret"]) def get_all_config(self, stack_name: str) -> ConfigMap: self.select_stack(stack_name) @@ -160,7 +160,8 @@ class LocalWorkspace(Workspace): config_json = json.loads(result.stdout) config_map: ConfigMap = {} for key in config_json: - config_map[key] = ConfigValue(**config_json[key]) + config_val_json = config_json[key] + config_map[key] = ConfigValue(value=config_val_json["value"], secret=config_val_json["secret"]) return config_map def set_config(self, stack_name: str, key: str, value: ConfigValue) -> None: diff --git a/sdk/python/lib/test/automation/data/nested_config/Pulumi.dev.yaml b/sdk/python/lib/test/automation/data/nested_config/Pulumi.dev.yaml new file mode 100644 index 000000000..048673b5c --- /dev/null +++ b/sdk/python/lib/test/automation/data/nested_config/Pulumi.dev.yaml @@ -0,0 +1,12 @@ +config: + aws:region: us-west-2 + nested_config:bar: 1234 + nested_config:foo: aha + nested_config:myList: + - one + - two + - three + nested_config:outer: + inner: + secure: AAABADOd8UPayqGlunla+Lo6kSSYA4LffCNBe84ElLwv0kyz7oIcYAw= + other: something_else diff --git a/sdk/python/lib/test/automation/data/nested_config/Pulumi.yaml b/sdk/python/lib/test/automation/data/nested_config/Pulumi.yaml new file mode 100644 index 000000000..80a948624 --- /dev/null +++ b/sdk/python/lib/test/automation/data/nested_config/Pulumi.yaml @@ -0,0 +1,3 @@ +name: nested_config +runtime: go +description: A minimal Go Pulumi program diff --git a/sdk/python/lib/test/automation/test_local_workspace.py b/sdk/python/lib/test/automation/test_local_workspace.py index 87ba37cb9..3546d0b99 100644 --- a/sdk/python/lib/test/automation/test_local_workspace.py +++ b/sdk/python/lib/test/automation/test_local_workspace.py @@ -20,6 +20,7 @@ from typing import List, Optional from pulumi import Config, export from pulumi.x.automation import ( create_stack, + create_or_select_stack, CommandError, ConfigMap, ConfigValue, @@ -28,7 +29,8 @@ from pulumi.x.automation import ( ProjectSettings, StackSummary, Stack, - StackAlreadyExistsError + StackAlreadyExistsError, + fully_qualified_stack_name, ) @@ -231,6 +233,28 @@ class TestLocalWorkspace(unittest.TestCase): ws.remove_stack(stack_name) + def test_nested_config(self): + stack_name = fully_qualified_stack_name("pulumi-test", "nested_config", "dev") + project_dir = test_path("data", "nested_config") + stack = create_or_select_stack(stack_name, work_dir=project_dir) + + all_config = stack.get_all_config() + outer_val = all_config["nested_config:outer"] + self.assertTrue(outer_val.secret) + self.assertEqual(outer_val.value, "{\"inner\":\"my_secret\",\"other\":\"something_else\"}") + + list_val = all_config["nested_config:myList"] + self.assertFalse(list_val.secret) + self.assertEqual(list_val.value, "[\"one\",\"two\",\"three\"]") + + outer = stack.get_config("outer") + self.assertTrue(outer.secret) + self.assertEqual(outer_val.value, "{\"inner\":\"my_secret\",\"other\":\"something_else\"}") + + arr = stack.get_config("myList") + self.assertFalse(arr.secret) + self.assertEqual(arr.value, "[\"one\",\"two\",\"three\"]") + def test_stack_status_methods(self): project_settings = ProjectSettings(name="python_test", runtime="python") ws = LocalWorkspace(project_settings=project_settings)