Как представить следующий JSON в Dhall? - PullRequest
0 голосов
/ 02 ноября 2019

Я использую следующий 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 немного сложнее обрабатывать из кода, и я не могу легко ссылаться на негоподмножество нашего инфра как с другим представлением.

Есть ли способ иметь ключи типа enums (объединение для пустых типов) с Dhall?

1 Ответ

1 голос
/ 03 ноября 2019

Это был бы идиоматический способ создания вложенных записей 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": {}
    }
  }
}
...