I'm working with a YAML file that contains annotations with specific values that need to be quoted. Here's an example of my input:
example/:
1. catalog-item-20='server1.test.local:80'
2. network-policy-version=v14.yaml
openshift.io/:
3. sa.scc.mcs='s0,c107,c49'
collectord.io/:
4. logs-index=channel_1
5. logs-override.11-match='^.*(%SENSITIVE%).*$'
I need to process this YAML and output it with proper quoting for values containing special characters. The desired output should look like this:
annotations:
example/catalog-item-20: 'server1.test.local:80'
bnhp.co.il/network-policy-version: v14.yaml
openshift.io/sa.scc.mcs: 's0,c107,c49'
collectord.io/logs-index: channel_1
collectord.io/logs-override.11-match: ^.*(%SENSITIVE%).*$
Notice that:
Here's my current code:
import yaml
with open('annotations.yaml', 'r') as f:
raw_annotations = yaml.safe_load(f)
annotations = {}
for annotations_prefix, annotations_body in raw_annotations.items():
prefix = annotations_prefix if annotations_prefix.endswith('/') else f"{annotations_prefix}/"
for value in annotations_body:
if '=' in value:
annotation_key, annotation_value = value.split('=', 1)
if annotation_value.startswith("'") and annotation_value.endswith("'"):
annotation_value = annotation_value[1:-1]
full_key = f"{prefix}{annotation_key}"
annotations[full_key] = annotation_value
namespace_content = {
'apiVersion': 'v1',
'kind': 'Namespace',
'metadata': {
'annotations': annotations
}
}
with open('namespace.yaml', 'w') as f:
yaml.dump(namespace_content, f, default_flow_style=False)
But this produces output without proper quotes:
annotations:
example/catalog-item-20: server1.test.local:80
openshift.io/sa.scc.mcs: s0,c107,c49
I've tried:
How can I make PyYAML preserve the quotes exactly as they appear in the input file?
I'm working with a YAML file that contains annotations with specific values that need to be quoted. Here's an example of my input:
example.com/:
1. catalog-item-20='server1.test.local:80'
2. network-policy-version=v14.yaml
openshift.io/:
3. sa.scc.mcs='s0,c107,c49'
collectord.io/:
4. logs-index=channel_1
5. logs-override.11-match='^.*(%SENSITIVE%).*$'
I need to process this YAML and output it with proper quoting for values containing special characters. The desired output should look like this:
annotations:
example.com/catalog-item-20: 'server1.test.local:80'
bnhp.co.il/network-policy-version: v14.yaml
openshift.io/sa.scc.mcs: 's0,c107,c49'
collectord.io/logs-index: channel_1
collectord.io/logs-override.11-match: ^.*(%SENSITIVE%).*$
Notice that:
Here's my current code:
import yaml
with open('annotations.yaml', 'r') as f:
raw_annotations = yaml.safe_load(f)
annotations = {}
for annotations_prefix, annotations_body in raw_annotations.items():
prefix = annotations_prefix if annotations_prefix.endswith('/') else f"{annotations_prefix}/"
for value in annotations_body:
if '=' in value:
annotation_key, annotation_value = value.split('=', 1)
if annotation_value.startswith("'") and annotation_value.endswith("'"):
annotation_value = annotation_value[1:-1]
full_key = f"{prefix}{annotation_key}"
annotations[full_key] = annotation_value
namespace_content = {
'apiVersion': 'v1',
'kind': 'Namespace',
'metadata': {
'annotations': annotations
}
}
with open('namespace.yaml', 'w') as f:
yaml.dump(namespace_content, f, default_flow_style=False)
But this produces output without proper quotes:
annotations:
example.com/catalog-item-20: server1.test.local:80
openshift.io/sa.scc.mcs: s0,c107,c49
I've tried:
How can I make PyYAML preserve the quotes exactly as they appear in the input file?
Your input is valid YAML, but there is no way the putput you present comes from the input and the program you specify:
aPIVersion
key at the root level of your expected output (and other stuff missing)1.
to 5.
That is a bit too much to correct your program, but in general in ruamel.yaml
setting .preserve_quotes
only affects loaded strings and
not newly created Python strings. You will have to create the special ruamel.yaml string subclasses that give you single quotes:
import sys
import ruamel.yaml
from pathlib import Path
def SQ(s):
return ruamel.yaml.scalarstring.SingleQuotedScalarString(s)
data = {'annotations': {
'example.com/catalog-item-20': SQ('server1.test.local:80'),
'bnhp.co.il/network-policy-version': 'v14.yaml',
'openshift.io/sa.scc.mcs': SQ('s0,c107,c49'),
'collectord.io/logs-index': 'channel_1',
'collectord.io/logs-override.11-match': '^.*(%SENSITIVE%).*$',
}}
output = Path('namespace.yaml')
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4)
yaml.dump(data, output)
sys.stdout.write(output.read_text())
which gives:
annotations:
example.com/catalog-item-20: 'server1.test.local:80'
bnhp.co.il/network-policy-version: v14.yaml
openshift.io/sa.scc.mcs: 's0,c107,c49'
collectord.io/logs-index: channel_1
collectord.io/logs-override.11-match: ^.*(%SENSITIVE%).*$
But you only have to do that if you process the output with a broken YAML parser (or some non-YAML tool), as these quotes are superfluous.
annotations:
require quotes one way or another, and to @CharlesDuffy's point they won't be meaningful to Kubernetes. A well-maintained YAML library should do the right thing when it's serializing data structures. – David Maze Commented Feb 4 at 16:14