파이썬에서 Yaml을 사용한 계층 구성.
최신 버전은 0.15.2입니다
Yaml 구문을 사용하여 계층 적 구성 파일을 병합 할 수있는 파이썬 모듈. 비밀 관리자의 깊은 병합, 가변 보간 및 비밀 검색을 제공합니다.
복제를 피하는 방식으로 계층 구조를 구성하려는 경우 이상적입니다. 환경/프로젝트/클러스터/앱과 같은 계층 구조를 사용하여 구성의 구조를 정의 할 수 있습니다. 이 계층 구조에서 사용하려는 레이어는 귀하에게 달려 있습니다. 이 도구는 루트에서 시작하는 모든 YAML 파일 (기본값이있는 경우)을 리프까지 읽습니다 (대부분의 특정 값이있는 경우, 우선 순위).
아이디어는 Puppet의 Hiera에서 나왔습니다.
pip 사용docker 이미지 사용dict 보간합니다pip 사용 pip install himldocker 이미지 사용 docker run ghcr.io/adobe/himl:latest himl-config-merger --helphttps://github.com/adobe/himl/pkgs/container/himl/versions의 모든 Docker 태그를 참조하십시오
git clone https://github.com/adobe/himl
cd himl
sudo python install -e .
Simple/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 himl 이라는 CLI 도구는 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 Anchors와 달리 이러한 보간은 여러 파일에서 작동합니다.
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)}} "금고 경로에서 모든 키/값 쌍을 검색하십시오.
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
Config-Merger 스크립트는 HIML을 활용하여 Configs 트리 구조를로드하고 루트 경로에서 가장자리로 찾은 모든 YAML 파일의 모든 키를 심화시킵니다. 각 잎 디렉토리의 경우 파일이 --output-dir 아래에서 생성됩니다.
각 레벨 아래에는 최종 결과를 계산하기 위해 Config-Merger가 사용하는 필수 "레벨 키"가 있습니다. 이 키는 각 레벨의 파일 중 하나에 있어야합니다. (예 : Env.yaml 아래).
디렉토리 트리의 더 높은 수준에 지정된 일부 구성은 끝 (LEAF) 결과에서 필요하지 않을 수 있습니다. 이러한 이유로 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 구성 요소는 또한 !include
예:
VA7 : !include configs/env=int/region=va7/kafka-brokers.yaml regionBrokers.VA7보간 후 값을 configs/env = int/region = va7/kafka-brokers.yaml path에서 찾은 greaBrokers.va7의 값으로 대체됩니다.
선택적 매개 변수 type_strategies 구성 프로세서로 전달하여 사용자 정의 병합 동작을 정의 할 수 있습니다. 귀하의 요구에 맞는 맞춤형 기능 일 수 있습니다. 기능은 (구성, 경로, 기본, 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" ])] ))