У меня есть файл yaml, который содержит несколько блоков yaml. Файл можно увидеть здесь.
В основном, я пытаюсь обновить значение для одного из ключей изображения (ctrl+f blockfreight/go-bftx:
в последнем блоке yaml файла. Тем не менее, я хочу сохранить все о файле (включая комментарии), за исключением одного значения, которое я обновляю.
У меня есть следующий код:
"""
Retrieves a truncated version of the latest git commit sha and updates
the go-bftx container image tag in app.yaml
"""
import sys
import ruamel.yaml
from subprocess import check_output
yaml_path = 'app.yaml'
for yaml_block in ruamel.yaml.round_trip_load_all(stream=open(yaml_path)):
pass
# parse the most recent git commit sha from command line
docker_image = 'blockfreight/go-bftx:ci-cd-' + check_output('git log -1 -- pretty=format:%h'.split()).decode()
# update go-bftx image with most recent git-commit-sha tag in the StatefulSet block
yaml_block['spec']['template']['spec']['containers'][1]['image'] = docker_image
ruamel.yaml.round_trip_dump(yaml_block, sys.stdout)
Это успешно редактирует значение, сохраняет комментарии нетронутыми, но отправляет только последний блок yaml в stdout.
Есть ли способ изменить только шестой (и последний) блок yaml в app.yaml и сохранить остальную часть файла в целости (комментарии включены)?
Я попробовал заменить pass
в приведенном выше коде инструкцией if, которая отправила первые пять yamls в stdout, а затем отредактировала значение в шестом значении, отправив его также в stdout. Мое мышление состояло в том, чтобы использовать bash для отправки всех файлов stdout в файл (например, python app_modifier.py > app1.yaml
), но это только отправило вывод из шестого yaml.
Этот код выглядел так:
for i, yaml_block in enumerate(ruamel.yaml.round_trip_load_all(stream=open(yaml_path))):
if i != 5:
ruamel.yaml.round_trip_dump(yaml_block, sys.stdout)
else:
# parse the most recent git commit sha from command line
docker_image = 'blockfreight/go-bftx:ci-cd-' + check_output('git log -1 --pretty=format:%h'.split()).decode()
# update go-bftx image with most recent git-commit-sha tag in the StatefulSet blocks
yaml_block['spec']['template']['spec']['containers'][1]['image'] = docker_image
ruamel.yaml.round_trip_dump(yaml_block, sys.stdout)
Будем очень благодарны любой помощи! Спасибо!
Ваш файл состоит из нескольких документов YAML, это то, что вы читаете при использовании round_trip_load_all
, который дает вам генератор.
Если вы пишете, что обратно с помощью round_trip_dump()
, вы никогда не собираетесь, чтобы получить ---
разделителей документов YAML, которые находятся в исходном файле.
Вероятно, вы можете использовать генератор и round_trip_dump_all
поскольку вы знаете, в каком документе внести изменения, но, вероятно, проще составить list
того, что round_trip_load_all
генерирует и работает над этим. Я также использовал ruamel.yaml
API ruamel.yaml
для этого:
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = list(yaml.load_all(open('app.yaml')))
# parse the most recent git commit sha from command line
# docker_image = 'blockfreight/go-bftx:ci-cd-' + check_output('git log -1 -- pretty=format:%h'.split()).decode()
docker_image = 'blockfreight/go-bftx:ci-cd-' + 'check_output_output'
# update go-bftx image with most recent git-commit-sha tag in the StatefulSet block
data[-1]['spec']['template']['spec']['containers'][1]['image'] = docker_image
with open('out.yaml', 'w') as ofp:
yaml.dump_all(data, ofp)
Вышеизложенное в основном работает. out.yaml
diff с изменением, которое вы хотите сделать, и некоторыми стандартными стандартами (отступы, между [ "
), которые, конечно, одно.
При таком подходе есть две основные проблемы:
#//Initializes BFTX Service to interact with endpoints
), который отбрасывается. Скорее всего, это ошибка в файле ruamel.yaml, которая отображается только в файлах с несколькими документами, и что я должен исследовать Чтобы решить первую проблему, вы можете читать этот документ только как обычные строки без ruamel.yaml
. Когда вы это сделаете, вы можете сделать все, кроме остального, поскольку это решает (то есть обходит) вторую проблему:
import sys
import ruamel.yaml
with open('out.yaml', 'w') as ofp:
lines = ''
with open('app.yaml') as ifp:
for line in ifp:
lines += line
if line == '---\n':
ofp.write(lines)
lines = ''
# process lines from the last document
# print(lines)
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(lines)
# parse the most recent git commit sha from command line
# docker_image = 'blockfreight/go-bftx:ci-cd-' + check_output('git log -1 -- pretty=format:%h'.split()).decode()
docker_image = 'blockfreight/go-bftx:ci-cd-' + 'check_output_output'
# update go-bftx image with most recent git-commit-sha tag in the StatefulSet block
data['spec']['template']['spec']['containers'][1]['image'] = docker_image
yaml.dump(data, ofp)
Это должно делать то, что вам нужно, если вы не заботитесь о ведущем концевом пространстве последовательности последовательности потоков или не сохраняете три места с несогласованным отступом. Выход diff -u app.yaml out.yaml
:
--- app.yaml 2018-06-23 14:41:02.256290577 +0200
+++ out.yaml 2018-06-23 14:58:09.933991459 +0200
@@ -143,7 +143,7 @@
spec:
selector:
matchLabels:
- app: bftx
+ app: bftx
serviceName: blockfreight
replicas: 1
template:
@@ -151,7 +151,7 @@
labels:
app: bftx
spec:
- containers:
+ containers:
- name: tm
imagePullPolicy: IfNotPresent
image: tendermint/tendermint:0.20.0
@@ -199,7 +199,7 @@
tendermint node --moniker="'hostname'" --p2p.seeds="[email protected]:8888,[email protected]:8888,[email protected]:8888,[email protected]:8888" --proxy_app="tcp://localhost:46658" --consensus.create_empty_blocks=false
- name: app
imagePullPolicy: Always
- image: blockfreight/go-bftx:rc1
+ image: blockfreight/go-bftx:ci-cd-check_output_output
ports:
- containerPort: 12345
- containerPort: 46658
@@ -247,7 +247,7 @@
- mountPath: /etc/nginx/conf.d/pub_key.conf
name: tmconfigdir
subPath: pub_key_nginx.conf
- volumes:
+ volumes:
- name: tmconfigdir
configMap:
name: bftx-config
@@ -262,7 +262,7 @@
annotations:
volume.alpha.kubernetes.io/storage-class: anything
spec:
- accessModes: [ "ReadWriteOnce" ]
+ accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
@@ -271,7 +271,7 @@
annotations:
volume.alpha.kubernetes.io/storage-class: anything
spec:
- accessModes: [ "ReadWriteOnce" ]
+ accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 12Mi