Konfigurasi hierarkis menggunakan YAML di Python.
Versi terbaru adalah: 0.15.2
Modul Python yang memungkinkan Anda untuk menggabungkan file konfigurasi hierarkis menggunakan sintaks YAML. Ini menawarkan gabungan yang mendalam, interpolasi variabel dan pengambilan rahasia dari manajer rahasia.
Sangat ideal jika Anda ingin menyusun hierarki Anda sedemikian rupa sehingga Anda menghindari duplikasi. Anda dapat mendefinisikan struktur untuk konfigurasi Anda menggunakan hierarki lingkungan/proyek/cluster/aplikasi tersebut. Terserah Anda lapisan apa yang ingin Anda gunakan dalam hierarki ini. Alat ini akan membaca semua file YAML mulai dari root (di mana nilai default akan) sampai ke daun (di mana nilai paling spesifik akan, yang akan diutamakan).
Ide datang dari Hiera Wayang.
pipdockerdictpip pip install himldocker docker run ghcr.io/adobe/himl:latest himl-config-merger --helpLihat semua tag Docker di: https://github.com/adobe/himl/pkgs/container/himl/versions
git clone https://github.com/adobe/himl
cd himl
sudo python install -e .
Ini akan menggabungkan sederhana/default.yaml dengan sederhana/produksi/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 ) Contoh di atas akan menggabungkan simple/default.yaml dengan simple/production/env.yaml :
$ tree examples/simple
examples/simple
├── default.yaml
└── production
└── env.yaml
Contohnya juga menampilkan penggabungan daftar dan peta yang mendalam.
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 :
- item3Hasil:
env : prod
deep :
key1 : v1
key2 : v2
key3 : v3
deep_list :
- item1
- item2
- item3 Alat CLI yang disebut himl secara otomatis diinstal melalui pip . Anda dapat menggunakannya untuk menguraikan pohon YAML dan itu akan menghasilkan konfigurasi gabungan pada output standar atau menulisnya ke file.
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=cluster2Berdasarkan pohon konfigurasi dari contoh/folder kompleks, output dari perintah di atas akan menjadi berikut:
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
Di mana folder contoh terlihat seperti ini:
$ 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
Untuk menghindari pengulangan, kami ingin memungkinkan untuk menentukan nilai sekali dan menggunakannya kembali di bagian lain dari konfigurasi YAML. Tidak seperti jangkar YAML, interpolasi ini bekerja di beberapa file.
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}} "Dimungkinkan untuk memiliki kunci yang sama (mis. Dikt/daftar) di banyak file dan menggabungkannya menggunakan penggabungan yang dalam. Lihat contoh di sini.
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)}} " Gunakan Vault CLI untuk mengotentikasi, Metode Fallback melalui LDAP.
Ambil hanya satu nilai kunci dari rahasia, ekor jalur digunakan sebagai kunci:
my_value : " {{vault.key(/path/from/vault/key)}} "Ambil semua pasangan kunci/nilai dari jalur lemari besi:
my_dict : " {{vault.path(/path/from/vault)}} "Menghasilkan token untuk suatu kebijakan:
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)}} " Skrip himl-config-merger , berisi logika menggabungkan direktori konfigurasi hierarkis dan membuat file YAML hasil akhir.
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
Contoh Input:
> 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
Keluaran:
merged_output
├── dev
│ ├── us-east-1
│ │ ├── cluster1.yaml
│ │ └── cluster2.yaml
│ └── us-west-2
│ └── cluster1.yaml
└── prod
└── eu-west-2
└── ireland1.yaml
Memanfaatkan HIML, skrip konfigurasi-merger memuat struktur pohon konfigurasi dan merge-merge semua kunci dari semua file YAML yang ditemukan dari jalur root ke tepi. Untuk setiap direktori daun, file akan dibuat di bawah --output-dir .
Di bawah setiap level, ada "kunci level" wajib yang digunakan oleh konfigurasi-merger untuk menghitung hasil akhir. Kunci ini harus ada di salah satu file di bawah setiap level. (mis. Env.yaml di bawah env).
Beberapa konfigurasi yang ditentukan dalam tingkat yang lebih tinggi dari pohon direktori mungkin tidak diperlukan pada hasil akhir (daun). Untuk alasan ini, skrip konfigurasi-merger dapat menerapkan satu set aturan filter yang ditentukan melalui parameter --filter-rules-key . Properti ini harus ada di konfigurasi dan berisi aturan untuk menghapus tombol level root dari output. Filter diterapkan jika objek pemilih cocok dengan subset dari tombol output dan akan menyimpan tombol yang ditentukan dalam daftar values atau tombol yang cocok dengan pola 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 :
- tagsBangun output dengan penyaringan:
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 Pemilih dan penyaringan aturan hanya berfungsi pada level root konfigurasi. Tidak mungkin untuk menyaring tombol bersarang.
Terlepas dari fitur standar yang ditemukan di pustaka PyYaml , komponen himl-config-merger juga mengimplementasikan tag YAML khusus yang disebut !include .
Contoh:
VA7 : !include configs/env=int/region=va7/kafka-brokers.yaml regionBrokers.VA7Ini akan menggantikan nilai setelah interpolasi dengan nilai regionalbrokers.va7 yang ditemukan di bawah jalur konfigurasi/env = int/region = va7/kafka-broker.yaml.
Parameter opsional type_strategies dapat diteruskan ke ConfigProcessor untuk mendefinisikan perilaku penggabungan khusus. Bisa jadi fungsi khusus yang sesuai dengan kebutuhan Anda. Fungsi Anda harus mengambil argumen (config, path, base, nxt) dan mengembalikan hasil gabungan.
Contoh:
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" ])] ))