تكوين هرمي باستخدام Yaml في Python.
أحدث إصدار هو: 0.15.2
وحدة Python التي تسمح لك بدمج ملفات التكوين الهرمية باستخدام بناء جملة YAML. إنه يوفر دمجًا عميقًا واستيفاء متغير واسترجاع الأسرار من مديري الأسرار.
إنه مثالي إذا كنت ترغب في تنظيم التسلسل الهرمي الخاص بك بطريقة تتجنب الازدواجية. يمكنك تحديد بنية لتكوينك باستخدام تسلسل هرمي مثل البيئة/المشروع/الكتلة/التطبيق. الأمر متروك لك ما هي الطبقات التي تريد استخدامها في هذا التسلسل الهرمي. ستقرأ الأداة جميع ملفات YAML التي تبدأ من الجذر (حيث ستكون القيم الافتراضية) وصولاً إلى الورقة (حيث ستكون معظم القيم المحددة ، والتي ستتخذ الأسبقية).
جاءت الفكرة من هايرا بوعاء.
pipdockerdict كلهpip pip install himldocker docker run ghcr.io/adobe/himl:latest himl-config-merger --helpانظر جميع علامات Docker على: https://github.com/adobe/himl/pkgs/container/himl/versions
git clone https://github.com/adobe/himl
cd himl
sudo python install -e .
هذا سوف يندمج بسيط/افتراضي
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}} "من الممكن أن يكون لديك نفس المفتاح (على سبيل المثال. القائمة/القائمة) في ملفات متعددة ودمجها باستخدام دمج عميق. انظر مثال هنا.
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)}} "استرداد جميع أزواج المفاتيح/القيمة من مسار قبو:
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 بتحميل بنية شجرة التكوينات وعمق جميع المفاتيح من جميع ملفات YAML الموجودة من مسار الجذر إلى حافة. لكل دليل ورقة ، سيتم إنشاء ملف ضمن- --output-dir .
تحت كل مستوى ، هناك "مفتاح مستوى" إلزامي يستخدم بواسطة تكوين تكوين لحساب النتيجة النهائية. يجب أن يكون هذا المفتاح موجودًا في أحد الملفات تحت كل مستوى. (على سبيل المثال ، env.yaml تحت ENV).
قد لا تكون هناك حاجة لبعض التكوينات المحددة في المستويات العليا لشجرة الدليل في نتيجة النهاية (ورقة). لهذا السبب ، يمكن أن يطبق برنامج Config-Merger Script مجموعة من قواعد المرشح المحددة عبر المعلمة --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-hers.yaml path.
يمكن تمرير type_strategies اختياري المعلمة إلى ConfigProcessor لتحديد سلوك دمج مخصص. يمكن أن تكون وظائف مخصصة تناسب احتياجاتك. يجب أن تأخذ وظيفتك وسيطات (التكوين ، المسار ، القاعدة ، 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" ])] ))