From eebdde1d6f98e550718711b67bcb40b81272dc91 Mon Sep 17 00:00:00 2001 From: Miguel Caballer Date: Tue, 1 Sep 2026 12:03:56 +0200 Subject: [PATCH] Fix error with special chars in inputs --- IM/tosca/Tosca.py | 16 +++++++++++----- test/unit/Tosca.py | 9 +++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/IM/tosca/Tosca.py b/IM/tosca/Tosca.py index cd9a4aa88..312f7a76c 100644 --- a/IM/tosca/Tosca.py +++ b/IM/tosca/Tosca.py @@ -880,6 +880,16 @@ def _get_implementation_url(self, node, implementation): return res + @staticmethod + def _serialize_interface_input(value): + if isinstance(value, str) and not value.startswith("|"): + # JSON strings are valid YAML scalars and correctly escape quotes, + # backslashes and control characters. + value = json.dumps(value) + else: + value = str(value) + return value.replace("\n", "\\n") + def _gen_configure_from_interfaces(self, node, compute, interfaces): if not interfaces: return None @@ -968,11 +978,7 @@ def _gen_configure_from_interfaces(self, node, compute, interfaces): if script_path.endswith(".yaml") or script_path.endswith(".yml"): if env: for var_name, var_value in env.items(): - if isinstance(var_value, str) and not var_value.startswith("|"): - var_value = '"%s"' % var_value - else: - var_value = str(var_value) - var_value = var_value.replace("\n", "\\n") + var_value = self._serialize_interface_input(var_value) variables += ' %s: %s ' % (var_name, var_value) + "\n" variables += "\n" diff --git a/test/unit/Tosca.py b/test/unit/Tosca.py index 7e8518450..5b76db388 100755 --- a/test/unit/Tosca.py +++ b/test/unit/Tosca.py @@ -586,6 +586,15 @@ def test_tosca_tls_get_att(self): self.assertEqual(conf['vars']['tls_cert_1_2'], "{{ hostvars[groups['server'][0]]['IM_NODE_TLS_CERTIFICATES']['cert1'] }}") + def test_interface_string_input_yaml_escaping(self): + value = 'password"with\\special\ncharacters' + serialized_value = Tosca._serialize_interface_input(value) + recipe = "---\n- vars:\n password: %s\n" % serialized_value + + parsed_recipe = yaml.safe_load(recipe) + + self.assertEqual(parsed_recipe[0]['vars']['password'], value) + if __name__ == "__main__": unittest.main()