การกำหนดค่าแบบลำดับชั้นโดยใช้ Yaml ใน Python
เวอร์ชันล่าสุดคือ: 0.15.2
โมดูล Python ที่ช่วยให้คุณสามารถรวมไฟล์กำหนดค่าแบบลำดับชั้นโดยใช้ไวยากรณ์ YAML มันมีการผสานอย่างลึกล้ำการแก้ไขตัวแปรและการดึงความลับจากผู้จัดการความลับ
เหมาะอย่างยิ่งหากคุณต้องการจัดโครงสร้างลำดับชั้นของคุณในลักษณะที่คุณหลีกเลี่ยงการทำซ้ำ คุณสามารถกำหนดโครงสร้างสำหรับการกำหนดค่าของคุณโดยใช้ลำดับชั้นสภาพแวดล้อม/โครงการ/คลัสเตอร์/แอป ขึ้นอยู่กับคุณว่าคุณต้องการใช้เลเยอร์ในลำดับชั้นนี้อะไร เครื่องมือจะอ่านไฟล์ YAML ทั้งหมดที่เริ่มต้นจากรูท (ซึ่งค่าเริ่มต้นจะเป็น) ไปจนถึง Leaf (ซึ่งค่าที่เฉพาะเจาะจงส่วนใหญ่จะเป็นซึ่งจะมีความสำคัญกว่า)
ความคิดมาจาก Hiera ของหุ่นเชิด
pipdockerdict ทั้งหมดpip pip install himldocker docker run ghcr.io/adobe/himl:latest himl-config-merger --helpดูแท็กนักเทียบท่าทั้งหมดได้ที่: https://github.com/adobe/himl/pkgs/container/himl/versions
git clone https://github.com/adobe/himl
cd himl
sudo python install -e .
สิ่งนี้จะรวมง่าย/default.yaml กับ Simple/Production/Env.yaml
from himl import ConfigProcessor
config_processor = ConfigProcessor ()
path = "examples/simple/production"
filters = () # can choose to output only specific keys
exclude_keys = () # can choose to remove specific keys
output_format = "yaml" # yaml/json
config_processor . process ( path = path , filters = filters , exclude_keys = exclude_keys ,
output_format = output_format , print_data = True ) ตัวอย่างข้างต้นจะรวม simple/default.yaml กับ simple/production/env.yaml :
$ tree examples/simple
examples/simple
├── default.yaml
└── production
└── env.yaml
ตัวอย่างยังแสดงการรวมรายการและแผนที่อย่างลึกซึ้ง
examples/simple/default.yaml
---
env : default
deep :
key1 : v1
key2 : v2
deep_list :
- item1
- item2 examples/simple/production/env.yaml
---
env : prod
deep :
key3 : v3
deep_list :
- item3ผลลัพธ์:
env : prod
deep :
key1 : v1
key2 : v2
key3 : v3
deep_list :
- item1
- item2
- item3 เครื่องมือ CLI ที่เรียกว่า himl จะถูกติดตั้งโดยอัตโนมัติผ่าน pip คุณสามารถใช้เพื่อแยกต้นไม้ของ Yamls และจะส่งออกการกำหนดค่ารวมที่เอาต์พุตมาตรฐานหรือเขียนลงในไฟล์
usage: himl [-h] [--output-file OUTPUT_FILE] [--format OUTPUT_FORMAT]
[--filter FILTER] [--exclude EXCLUDE]
[--skip-interpolation-validation]
[--skip-interpolation-resolving] [--enclosing-key ENCLOSING_KEY]
[--cwd CWD]
[--list-merge-strategy {append,override,prepend,append_unique}]
pathhiml examples/complex/env=dev/region=us-east-1/cluster=cluster2ขึ้นอยู่กับแผนผังการกำหนดค่าจากตัวอย่าง/โฟลเดอร์ที่ซับซ้อนเอาต์พุตของคำสั่งด้านบนจะเป็นสิ่งต่อไปนี้:
cluster:
description: 'This is cluster: cluster2. It is using c3.2xlarge instance type.'
name: cluster2
node_type: c3.2xlarge
region:
location: us-east-1
env: dev
ที่โฟลเดอร์ตัวอย่างมีลักษณะเช่นนี้:
$ tree examples/complex
examples/complex
├── default.yaml
├── env=dev
│ ├── env.yaml
│ ├── region=us-east-1
│ │ ├── cluster=cluster1
│ │ │ └── cluster.yaml
│ │ ├── cluster=cluster2
│ │ │ └── cluster.yaml
│ │ └── region.yaml
│ └── region=us-west-2
│ ├── cluster=cluster1
│ │ └── cluster.yaml
│ └── region.yaml
└── env=prod
├── env.yaml
└── region=eu-west-2
├── cluster=ireland1
│ └── cluster.yaml
└── region.yaml
เพื่อหลีกเลี่ยงการทำซ้ำเราต้องการทำให้เป็นไปได้ที่จะกำหนดค่าหนึ่งครั้งและนำกลับมาใช้ใหม่ในส่วนอื่น ๆ ของการกำหนดค่า YAML ซึ่งแตกต่างจากแองเคอร์ Yaml การแก้ไขเหล่านี้ทำงานในหลาย ๆ ไฟล์
data/default.yaml :
allowed_roles :
- " arn:aws:iam::{{account.id}}:role/myrole " data/dev/env.yaml :
account:
id: "123456"
dict ทั้งหมด projects :
webapp1 :
tagging :
Owner : " Web Service Team "
Environment : " dev "
CostCenter : " 123 "
data-store :
Owner : " Backend Team "
Environment : " dev "
CostCenter : " 455 "
# this will copy the whole projects.webapp1.tagging dict to this key
tagging : " {{projects.webapp1.tagging}} "
# or even a double interpolation
tagging : " {{projects.{{project.name}}.tagging}} "เป็นไปได้ที่จะมีคีย์เดียวกัน (เช่น dict/list) ในหลายไฟล์และรวมไว้โดยใช้การผสานลึก ดูตัวอย่างที่นี่
passphrase : " {{ssm.path(/key/coming/from/aws/secrets/store/manager).aws_profile(myprofile)}} " my_value : " {{s3.bucket(my-bucket).path(path/to/file.txt).base64encode(true).aws_profile(myprofile)}} " ใช้ Vault CLI เพื่อตรวจสอบความถูกต้องวิธีทางเลือกผ่าน LDAP
ดึงค่าคีย์เพียงหนึ่งค่าจากความลับหางเส้นทางถูกใช้เป็นคีย์:
my_value : " {{vault.key(/path/from/vault/key)}} "ดึงคู่คีย์/ค่าทั้งหมดจากเส้นทาง vault:
my_dict : " {{vault.path(/path/from/vault)}} "สร้างโทเค็นสำหรับนโยบาย:
my_token : " {{vault.token_policy(my_vault_policy)}} " # ## Terraform remote states ###
remote_states :
- name : cluster_composition
type : terraform
aws_profile : " my_aws_profile "
s3_bucket : " my_terraform_bucket "
s3_key : " mycluster.tfstate "
endpoint : " {{outputs.cluster_composition.output.value.redis_endpoint}} " kubeconfig_location : " {{env(KUBECONFIG)}} " สคริปต์ himl-config-merger มีตรรกะของการรวมไดเรกทอรีการกำหนดค่าแบบลำดับชั้นและสร้างไฟล์ผลลัพธ์สุดท้ายของ YAML
himl-config-merger examples/complex --output-dir merged_output --levels env region cluster --leaf-directories cluster INFO:__main__:Found input config directory: examples/complex/env=prod/region=eu-west-2/cluster=ireland1
INFO:__main__:Storing generated config to: merged_output/prod/eu-west-2/ireland1.yaml
INFO:__main__:Found input config directory: examples/complex/env=dev/region=us-west-2/cluster=cluster1
INFO:__main__:Storing generated config to: merged_output/dev/us-west-2/cluster1.yaml
INFO:__main__:Found input config directory: examples/complex/env=dev/region=us-east-1/cluster=cluster1
INFO:__main__:Storing generated config to: merged_output/dev/us-east-1/cluster1.yaml
INFO:__main__:Found input config directory: examples/complex/env=dev/region=us-east-1/cluster=cluster2
INFO:__main__:Storing generated config to: merged_output/dev/us-east-1/cluster2.yaml
ตัวอย่างอินพุต:
> tree examples/complex
examples/complex
├── default.yaml
├── env=dev
│ ├── env.yaml
│ ├── region=us-east-1
│ │ ├── cluster=cluster1
│ │ │ └── cluster.yaml
│ │ ├── cluster=cluster2
│ │ │ └── cluster.yaml
│ │ └── region.yaml
│ └── region=us-west-2
│ ├── cluster=cluster1
│ │ └── cluster.yaml
│ └── region.yaml
└── env=prod
├── env.yaml
└── region=eu-west-2
├── cluster=ireland1
│ └── cluster.yaml
└── region.yaml
เอาท์พุท:
merged_output
├── dev
│ ├── us-east-1
│ │ ├── cluster1.yaml
│ │ └── cluster2.yaml
│ └── us-west-2
│ └── cluster1.yaml
└── prod
└── eu-west-2
└── ireland1.yaml
การใช้ประโยชน์จาก HIML สคริปต์ config-merger จะโหลดโครงสร้างต้นไม้ configs และลึกลงไปที่คีย์ทั้งหมดจากไฟล์ YAML ทั้งหมดที่พบจากเส้นทางรูทไปยังขอบ สำหรับแต่ละไดเรกทอรี Leaf ไฟล์จะถูกสร้างขึ้นภายใต้ --output-dir
ภายใต้แต่ละระดับจะมี "คีย์ระดับ" บังคับที่ใช้โดย config-merger สำหรับการคำนวณผลลัพธ์สุดท้าย คีย์นี้ควรมีอยู่ในไฟล์ใดไฟล์หนึ่งภายใต้แต่ละระดับ (เช่น env.yaml ภายใต้ env)
การกำหนดค่าบางอย่างที่ระบุไว้ในระดับที่สูงขึ้นของแผนผังไดเรกทอรีอาจไม่จำเป็นในผลลัพธ์ (ใบไม้) ด้วยเหตุผลนี้สคริปต์ config-merger สามารถใช้ชุดของกฎตัวกรองที่ระบุผ่านพารามิเตอร์ --filter-rules-key คุณสมบัตินี้จะต้องมีอยู่ในการกำหนดค่าและมีกฎสำหรับการลบคีย์ระดับรูทออกจากเอาต์พุต ตัวกรองจะถูกนำไปใช้หากวัตถุตัวเลือกตรงกับชุดย่อยของปุ่มเอาต์พุตและจะเก็บคีย์ที่ระบุไว้ในรายการ values หรือคีย์ที่ตรงกับรูปแบบ regex
# intermediate config after hierarchical merge
env : dev
cluster : cluster1
region : us-east-1
key1 : persisted
key2 : dropped
keep_1 : persisted
tags :
cost_center : 123
_filters :
- selector :
env : " dev "
keys :
values :
- key1
regex : " keep_.* "
- selector :
cluster :
regex : " cluster1 "
keys :
values :
- tagsสร้างผลลัพธ์ด้วยการกรอง:
himl-config-merger examples/filters --output-dir merged_output --levels env region cluster --leaf-directories cluster --filter-rules-key _filters # output after filtering
env : dev
cluster : cluster1
region : us-east-1
key1 : persisted
keep_1 : persisted
tags :
cost_center : 123 ตัวเลือกกฎและคีย์การกรองจะทำงานได้ที่ระดับรูทของการกำหนดค่าเท่านั้น เป็นไปไม่ได้ที่จะกรองปุ่มที่ซ้อนกัน
นอกเหนือจากคุณสมบัติมาตรฐานที่พบในไลบรารี PyYaml แล้วองค์ประกอบ himl-config-merger ยังใช้แท็ก YAML ที่กำหนดเองที่เรียกว่า !include
ตัวอย่าง:
VA7 : !include configs/env=int/region=va7/kafka-brokers.yaml regionBrokers.VA7สิ่งนี้จะแทนที่ค่าหลังจากการแก้ไขด้วยค่าของ regionbrokers.va7 ที่พบภายใต้ configs/env = int/region = va7/kafka-brokers.yaml
พารามิเตอร์ตัวเลือก type_strategies สามารถส่งผ่านไปยัง configprocessor เพื่อกำหนดพฤติกรรมการผสานแบบกำหนดเอง อาจเป็นฟังก์ชั่นที่กำหนดเองที่เหมาะสมกับความต้องการของคุณ ฟังก์ชั่นของคุณควรใช้อาร์กิวเมนต์ของ (config, path, base, nxt) และส่งคืนผลลัพธ์ที่ผสาน
ตัวอย่าง:
from himl import ConfigProcessor
def strategy_merge_override ( config , path , base , nxt ):
"""merge list of dicts. if objects have same id, nxt replaces base."""
"""if remove flag is present in nxt item, remove base and not add nxt"""
result = deepcopy ( base )
for nxto in nxt :
for baseo in result :
# if list is not a list of dicts, bail out and let the next strategy to execute
if not isinstance ( baseo , dict ) or not isinstance ( nxto , dict ):
return STRATEGY_END
if 'id' in baseo and 'id' in nxto and baseo [ 'id' ] == nxto [ 'id' ]:
result . remove ( baseo ) #same id, remove previous item
if 'remove' not in nxto :
result . append ( nxto )
return result
config_processor = ConfigProcessor ()
path = "examples/simple/production"
filters = () # can choose to output only specific keys
exclude_keys = () # can choose to remove specific keys
output_format = "yaml" # yaml/json
config_processor . process ( path = path , filters = filters , exclude_keys = exclude_keys ,
output_format = output_format , print_data = True ,
type_strategies = [( list , [ strategy_merge_override , 'append' ]), ( dict , [ "merge" ])] ))