在开发容器发布系统的时候,由于需要调用k8s的API,故需要和k8s的deployment、service等YAML内容格式打交道。
先来介绍一下YAML
YAML 全名 YAML Ain’t Markup Language,主要设计目标是对人类可读性高。
YAML 1.2 是 JSON 的超集,也就是说合法的 JSON 扔给 YAML 1.2 解析器是可以被完美解析的
YAML一般来说,做序列化和做配置文件的场景比较多。
另外,YAML是可以转化为Json格式的
在Python中操作yaml有两种做法:
pip3 install pyyaml
pip3 install ruamel.yaml
pyyaml是python自带的官方包,官方文档为:https://pyyaml.org/wiki/PyYAML
安装:
pip3 install pyyaml
读取:yaml.load
import yaml
# 读取yaml内容
yaml_content = yaml.load("""
name: Vorlin Laruknuzum
sex: Male
class: Priest
title: Acolyte
hp: [32, 71]
sp: [1, 13]
gold: 423
inventory:
- a Holy Book of Prayers (Words of Wisdom)
- an Azure Potion of Cure Light Wounds
- a Silver Wand of Wonder
""", Loader=yaml.FullLoader)
print(yaml_content['name'])
# 读取yaml文件
with open(r'test.yaml', 'r') as f:
yaml.load(f, Loader=yaml.FullLoader)
写入:yaml.dump
import yaml
# 读取yaml内容
yaml_content = yaml.load("""
name: Vorlin Laruknuzum
sex: Male
class: Priest
title: Acolyte
hp: [32, 71]
sp: [1, 13]
gold: 423
inventory:
- a Holy Book of Prayers (Words of Wisdom)
- an Azure Potion of Cure Light Wounds
- a Silver Wand of Wonder
""", Loader=yaml.FullLoader)
yaml_content['name'] = 'New Name'
new_yaml = yaml.dump(yaml_content)
print(new_yaml)
但是呢,yaml.dump
是有点问题的:
比如这里有个例子:
yaml内容为:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
annotations:
creator: admin
description: mbs-statement-service
owner_name: mbs-statement-service
sidecar.istio.io/inject: "false"
creationTimestamp: null
labels:
app: mbs-statement-service
version: "07071418"
name: mbs-statement-service-07071418
namespace: bankapp
spec:
replicas: 1
selector:
matchLabels:
app: mbs-statement-service
version: "07071418"
strategy: {}
template:
metadata:
annotations:
creator: admin
description: mbs-statement-service
owner_name: mbs-statement-service
sidecar.istio.io/inject: "false"
creationTimestamp: null
labels:
app: mbs-statement-service
version: "07071418"
name: mbs-statement-service-07071418
namespace: bankapp
spec:
containers:
- command:
- /bin/sh
- -c
- /usr/local/jdk1.8.0_172/bin/java -jar $(JAVA_OPTS) $(GCLOG_OPTS) $(SHOOTING_OPTS)
$(APOLLO_OPTS)
mbs-statement-service.jar
image: vb-harbor.in.xx/xxx/mbs-statement-service:uat_20200528_v2
imagePullPolicy: IfNotPresent
使用PyYaml来处理的话:
import yaml
deployment_obj = yaml.load(yaml_content, Loader=yaml.FullLoader)
for key, containers in enumerate(deployment_obj['spec']['template']['spec']['containers']):
deployment_obj['spec']['template']['spec']['containers'][key]['image'] = "$IMAGE_URL"
k8s_deployment = yaml.dump(deployment_obj)
print(k8s_deployment)
打印出来后,格式有问题,version的双引号丢失了:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
annotations:
creator: admin
description: mbs-statement-service
owner_name: mbs-statement-service
sidecar.istio.io/inject: 'false'
creationTimestamp: null
labels:
app: mbs-statement-service
version: 07071418
name: mbs-statement-service-07071418
namespace: bankapp
spec:
replicas: 1
selector:
matchLabels:
app: mbs-statement-service
version: 07071418
strategy: {}
template:
metadata:
annotations:
creator: admin
description: mbs-statement-service
owner_name: mbs-statement-service
sidecar.istio.io/inject: 'false'
creationTimestamp: null
labels:
app: mbs-statement-service
version: 07071418
name: mbs-statement-service-07071418
namespace: bankapp
spec:
containers:
- command:
- /bin/sh
- -c
- /usr/local/jdk1.8.0_172/bin/java -jar $(JAVA_OPTS) $(GCLOG_OPTS) $(SHOOTING_OPTS)
$(APOLLO_OPTS) mbs-statement-service.jar
image: $IMAGE_URL
imagePullPolicy: IfNotPresent
使用default_style
来进行处理
import yaml
deployment_obj = yaml.load(yaml_content, Loader=yaml.FullLoader)
for key, containers in enumerate(deployment_obj['spec']['template']['spec']['containers']):
deployment_obj['spec']['template']['spec']['containers'][key]['image'] = "$IMAGE_URL"
k8s_deployment = yaml.dump(deployment_obj, default_style='"')
print(k8s_deployment)
打印出来问题更大,会出现:"replicas": !!int "1"
"apiVersion": "apps/v1beta1"
"kind": "Deployment"
"metadata":
"annotations":
"creator": "admin"
"description": "mbs-statement-service"
"owner_name": "mbs-statement-service"
"sidecar.istio.io/inject": "false"
"creationTimestamp": !!null "null"
"labels":
"app": "mbs-statement-service"
"version": "07071418"
"name": "mbs-statement-service-07071418"
"namespace": "bankapp"
"spec":
"replicas": !!int "1"
"selector":
"matchLabels":
"app": "mbs-statement-service"
"version": "07071418"
"strategy": {}
"template":
"metadata":
"annotations":
"creator": "admin"
"description": "mbs-statement-service"
"owner_name": "mbs-statement-service"
"sidecar.istio.io/inject": "false"
"creationTimestamp": !!null "null"
"labels":
"app": "mbs-statement-service"
"version": "07071418"
"name": "mbs-statement-service-07071418"
"namespace": "bankapp"
"spec":
"containers":
- "command":
- "/bin/sh"
- "-c"
- "/usr/local/jdk1.8.0_172/bin/java -jar $(JAVA_OPTS) $(GCLOG_OPTS) $(SHOOTING_OPTS)\
\ $(APOLLO_OPTS) mbs-statement-service.jar"
"image": "$IMAGE_URL"
"imagePullPolicy": "IfNotPresent"
所以得使用下面的ruamel,使用下面的ruamel的话并不会去掉version后面的引号
PyYaml应用最广泛,但是封装的API不够简单,而且不支持YAML 1.2最新版,所以可以使用ruamel来替代,ruamel.yaml是PyYaml的衍生版,封装的API简单而且支持YAML 1.2最新版
用法基本上也和PyYAML差不多
安装
pip3 install ruamel.yaml
读取:yaml.load
from ruamel import yaml
# 读取yaml内容
yaml_content = yaml.load("""
name: Vorlin Laruknuzum
sex: Male
class: Priest
title: Acolyte
hp: [32, 71]
sp: [1, 13]
gold: 423
inventory:
- a Holy Book of Prayers (Words of Wisdom)
- an Azure Potion of Cure Light Wounds
- a Silver Wand of Wonder
""", Loader=yaml.Loader)
print(yaml_content['name'])
# 读取yaml文件
with open(r'test.yaml', 'r') as f:
yaml.load(f, Loader=yaml.Loader)
写入:yaml.dump
from ruamel import yaml
# 读取yaml内容
yaml_content = yaml.load("""
name: Vorlin Laruknuzum
sex: Male
class: Priest
title: Acolyte
hp: [32, 71]
sp: [1, 13]
gold: 423
inventory:
- a Holy Book of Prayers (Words of Wisdom)
- an Azure Potion of Cure Light Wounds
- a Silver Wand of Wonder
""", Loader=yaml.Loader)
yaml_content['name'] = 'New Name'
new_yaml = yaml.dump(yaml_content, Dumper=yaml.RoundTripDumper)
print(new_yaml)
python – pyyaml并仅使用字符串引号
python:yaml模块
python笔记20-yaml文件写入(ruamel.yaml)