我正在使用以下JSON表示我们的基础结构。这是一个大大简化的版本。
{
"us-east-1": {
"qa": {
"etcd": {}
}
},
"eu-central-1": {
"dev": {
"etcd": {}
}
},
"eu-west-1": {
"prod": {
"etcd": {}
}
}
}
这可以映射到文件夹,并且很容易从代码中处理。
#!/usr/bin/env python
import json
import os, sys
with open('infrastructure.json', 'r') as read_file: infra = json.load(read_file)
regions = infra.keys()
for region in regions:
stages = infra[region].keys()
for stage in stages:
apps = infra[region][stage].keys()
for app in apps:
os.makedirs(os.path.join('infra', region, stage, app), 0o750, exist_ok=True)
print('region: {}, stage: {}, app: {}'.format(region, stage, app))
但是,我想使用Dhall生成此文件以将可能的键限制为列表。
Dhall为此提供支持:
let AwsRegions : Type = < us-east-1 | eu-central-1 | eu-west-1 >
let Stages : Type = < dev | qa | prod >
let Applications : Type = < etcd | postgresql | hadoop >
唯一的问题是我找不到将记录键作为空类型的支持,只能将值限制为那些。
这使我可以通过以下方式进行操作:
let infrastructure :
List { region: AwsRegions, stage: Stages,
applications: List Applications } =
[ { region = AwsRegions.us-east-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-central-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.qa,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.prod,
applications = [
Applications.hadoop,
Applications.etcd ] } ]
in infrastructure
从代码中处理生成的JSON有点困难,而且我无法像其他表示形式那样轻易地引用我们的基础设施的子集。
是否可以通过Dhall拥有像枚举(空类型的并集)之类的键?
答案 0 :(得分:1)
这将是生成嵌套JSON记录的惯用方式,其记录的键仅限于枚举:
let keyValue =
λ(k : Type)
→ λ(v : Type)
→ λ(mapKey : k)
→ λ(mapValue : v)
→ { mapKey = mapKey, mapValue = mapValue }
let Prelude = https://prelude.dhall-lang.org/v11.1.0/package.dhall
let Application = < etcd | postgresql | hadoop >
let Applications = Prelude.Map.Type Application {}
let application = λ(application : Application) → keyValue Application {} application {=}
let Stage = < dev | qa | prod >
let Stages = Prelude.Map.Type Stage Applications
let stage = keyValue Stage Applications
let AwsRegion = < us-east-1 | eu-central-1 | eu-west-1 >
let AwsRegions = Prelude.Map.Type AwsRegion Stages
let awsRegion = keyValue AwsRegion Stages
in [ awsRegion AwsRegion.us-east-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
]
, awsRegion AwsRegion.eu-west-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
, stage Stage.qa
[ application Application.hadoop
, application Application.etcd
]
, stage Stage.prod
[ application Application.hadoop
, application Application.etcd
]
]
, awsRegion AwsRegion.eu-central-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
]
]
...呈现为以下JSON:
$ dhall-to-json/dhall-to-json --file /tmp/test/example.dhall
{
"eu-central-1": {
"dev": {
"etcd": {},
"hadoop": {}
}
},
"eu-west-1": {
"dev": {
"etcd": {},
"hadoop": {}
},
"prod": {
"etcd": {},
"hadoop": {}
},
"qa": {
"etcd": {},
"hadoop": {}
}
},
"us-east-1": {
"dev": {
"etcd": {},
"hadoop": {}
}
}
}