Pyyaml: изменить aws-auth-cm.yaml, сохранить многострочную строку - PullRequest
1 голос
/ 24 июня 2019

Я пытаюсь загрузить YAML-файл в python, изменить его и вернуть обратно.YAML выглядит следующим образом:

data:
  mapRoles: |
    - username: system:node:{{EC2PrivateDNSName}}
      groups:
      - system:bootstrappers
      - system:nodes
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system

Я хотел бы изменить его так, чтобы выходной файл включал новую строку rolearn: awsarn в mapRoles:

data:
  mapRoles: |
    - username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
      rolearn: awsarn
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system

Но я получаювыведите это, где значение mapRoles будет заключено в кавычки как строка и содержит литерал \n:

apiVersion: v1
data:
  mapRoles: "- username: system:node:{{EC2PrivateDNSName}}\n  groups:\n    - system:bootstrappers\n\
    \    - system:nodes\n  rolearn: arnaws"
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system

Код, который я использую:

with open ('/tmp/aws-auth-cm.yaml') as f:
  content = yaml.safe_load(f)
  content['data']['mapRoles'] = content['data']['mapRoles'] + '  rolearn: awsarn' 
with open("/tmp/aws-auth-cm.yaml", "w") as f:
  yaml.safe_dump(content, f, default_flow_style=False)

Я также пытался использовать yaml.safe_dump(content, f, default_flow_style=False, default_style='|')тогда все значения имеют | - и ключи заключаются в двойные кавычки:

"apiVersion": |-
  v1
"data":
  "mapRoles": |-
    - username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
      rolearn: arnaws
"kind": |-
  ConfigMap
"metadata":
  "name": |

Есть ли способ, которым я мог бы применить стиль = '|'только для строк, а также убедитесь, что ключи не в кавычках?

1 Ответ

1 голос
/ 25 июня 2019

Вы можете попытаться сделать это с PyYAML, но вам нужно загрузить литеральный скаляр стилевого стиля (именно так называется такая многострочная конструкция, обозначенная |) в подкласс строки, убедитесь, чтоВы можете изменить его, а затем при дампе использовать специальный представитель для этого подкласса, который снова создает дамп в виде буквального скаляра.

Самый простой способ сделать это - перейти с PyYAML на ruamel.yaml (отказ от ответственности: я авторэтого пакета), он не только сохраняет литеральный блок, но также поддерживает более актуальную спецификацию YAML 1.2 (выпущена в 2009 году), сохраняет комментарии и теги, целочисленные и плавающие форматы и (необязательно) лишние кавычки:

import sys
import ruamel.yaml


yaml = ruamel.yaml.YAML()
with open('aws-auth-cm.yaml') as f:
    content = yaml.load(f)
content['data']['mapRoles'] += '  rolearn: awsarn\n'
with open('aws-auth-cm.yaml', 'w') as f:
    yaml.dump(content, f)

, что дает:

data:
  mapRoles: |
    - username: system:node:{{EC2PrivateDNSName}}
      groups:
      - system:bootstrappers
      - system:nodes
      rolearn: awsarn
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system

Обратите внимание, что я сохранил некоторую печать с помощью +=, чтобы изменить «строку», загруженную из литерального скаляра.И что я добавил новую строку в конец добавленной строки, потому что в противном случае ваш буквальный скаляр будет введен с |-, - является оператором блочной компоновки , указывающим stripping .

...