From 4dcc0d631eaacb4329ae8dc7518e79e88859f8a1 Mon Sep 17 00:00:00 2001 From: Komal Date: Thu, 15 Apr 2021 11:41:25 -0700 Subject: [PATCH] [automation/python] - Fix stack settings serialization (#6776) --- .../lib/pulumi/automation/_stack_settings.py | 52 ++++++++++++------- .../test/automation/test_local_workspace.py | 19 +++++++ 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/sdk/python/lib/pulumi/automation/_stack_settings.py b/sdk/python/lib/pulumi/automation/_stack_settings.py index 3433380bc..e2d756471 100644 --- a/sdk/python/lib/pulumi/automation/_stack_settings.py +++ b/sdk/python/lib/pulumi/automation/_stack_settings.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, Mapping, Any, Union, Dict +from typing import Optional, Any, Dict class StackSettingsSecureConfigValue: @@ -28,38 +28,52 @@ class StackSettings: secrets_provider: Optional[str] encrypted_key: Optional[str] encryption_salt: Optional[str] - config: Optional[Mapping[str, Any]] + config: Optional[Dict[str, Any]] def __init__(self, secrets_provider: Optional[str] = None, encrypted_key: Optional[str] = None, encryption_salt: Optional[str] = None, - config: Optional[Mapping[str, Any]] = None): + config: Optional[Dict[str, Any]] = None): self.secrets_provider = secrets_provider self.encrypted_key = encrypted_key self.encryption_salt = encryption_salt - if config: - stack_config: Dict[str, Union[str, StackSettingsSecureConfigValue]] = {} - for key in config: - val = config[key] + self.config = config + + @classmethod + def _deserialize(cls, data: dict): + config = data.get("config") + if config is not None: + stack_config: Dict[str, Any] = {} + for key, val in config.items(): if isinstance(val, str): stack_config[key] = val elif "secure" in val: stack_config[key] = StackSettingsSecureConfigValue(**val) - if len(stack_config.keys()) > 0: - self.config = stack_config - - @classmethod - def _deserialize(cls, data: dict): + config = stack_config return cls(secrets_provider=data.get("secretsprovider"), encrypted_key=data.get("encryptedkey"), encryption_salt=data.get("encryptionsalt"), - config=data.get("config")) + config=config) def _serialize(self): - return { - "secretsprovider": self.secrets_provider, - "encryptedkey": self.encrypted_key, - "encryptionsalt": self.encryption_salt, - "config": self.config - } + serializable = {} + + # Only add the keys that are present to avoid writing nulls to the + # Pulumi.[stack].yaml file. + if self.secrets_provider: + serializable["secretsprovider"] = self.secrets_provider + if self.encrypted_key: + serializable["encryptedkey"] = self.encrypted_key + if self.encryption_salt: + serializable["encryptionsalt"] = self.encryption_salt + if self.config: + config = {} + for key, val in self.config.items(): + if isinstance(val, StackSettingsSecureConfigValue): + config[key] = {"secure": val.secure} + else: + config[key] = val + serializable["config"] = config + + return serializable diff --git a/sdk/python/lib/test/automation/test_local_workspace.py b/sdk/python/lib/test/automation/test_local_workspace.py index 3d0782c63..346bf1ee0 100644 --- a/sdk/python/lib/test/automation/test_local_workspace.py +++ b/sdk/python/lib/test/automation/test_local_workspace.py @@ -34,6 +34,7 @@ from pulumi.automation import ( ProjectSettings, StackSummary, Stack, + StackSettings, StackAlreadyExistsError, fully_qualified_stack_name, ) @@ -106,6 +107,24 @@ class TestLocalWorkspace(unittest.TestCase): self.assertEqual(settings.config["plain"], "plain") self.assertEqual(settings.config["secure"].secure, "secret") + settings_with_no_config = StackSettings(secrets_provider="blah", + encrypted_key="thisiskey", + encryption_salt="salty") + self.assertEqual(settings_with_no_config._serialize(), { + "secretsprovider": "blah", + "encryptedkey": "thisiskey", + "encryptionsalt": "salty" + }) + + config = { + "cool": "sup", + "foo": {"secure": "thisisasecret"}, + } + settings_with_only_config = StackSettings(config=config) + self.assertEqual(settings_with_only_config._serialize(), { + "config": config + }) + def test_plugin_functions(self): ws = LocalWorkspace() # Install aws 3.0.0 plugin