2

我将从一个几乎代表特使代理配置的配置示例开始:)


virtual_hosts:
- name: webxp-api_http
  domains: ["*"]
  routes:
  - match: { prefix: "/static/v5.0" }
    route: { cluster: bodhi_static }
  - match: { prefix: "/"}
    route: { cluster: bodhi-web }

  clusters:
  - name: bodhi_web
  - name: bodhi_static

规则是,必须定义该名称clusters列表必须定义为在route配置部分中使用。如果您仔细观察,此配置将无法加载,因为bodhi_webis not bodhi-web. 我将如何在 Dhall 中对其进行编码?

一方面,我可以clusters在 let 绑定中作为列表,这会有所帮助,但没有什么强迫我使用绑定,实际上我希望将其clusters视为cluster:字段的总和类型?依赖类型可以在这里帮助我吗(即我记得在纯脚本中做了类似的事情,它对依赖类型编程的能力有限)

还是我应该只创建一个构造函数/验证器函数并滥用断言来验证它?

还是我不应该?:)

4

2 回答 2

1

我将通过编写一个生成正确构造配置的实用程序函数来解决这个问题。

使用您的示例,如果我们想确保该clusters字段下方的列表始终与路线列表匹配,那么我们从该字段派生该clusters字段routes

let Prelude = https://prelude.dhall-lang.org/package.dhall

let Route = { match : { prefix : Text }, route : { cluster : Text } }

let toVirtualHosts =
          \(args : { name : Text, domains : List Text, routes : List Route })
      ->  { virtual_hosts =
                  args
              //  { clusters =
                      Prelude.List.map
                        Route
                        Text
                        (\(r : Route) -> r.route.cluster)
                        args.routes
                  }
          }

in  toVirtualHosts
      { name = "webxp-api_http"
      , domains = [ "*" ]
      , routes =
          [ { match = { prefix = "/static/v5.0" }
            , route = { cluster = "bodhi_static" }
            }
          , { match = { prefix = "/" }
            , route = { cluster = "bodhi_web" }
            }
          ]
      }
$ dhall-to-yaml --file ./example.dhall
virtual_hosts:
  clusters:
  - bodhi_static
  - bodhi_web
  domains:
  - *
  name: webxp-api_http
  routes:
  - match:
      prefix: /static/v5.0
    route:
      cluster: bodhi_static
  - match:
      prefix: /
    route:
      cluster: bodhi_web
于 2019-12-04T16:58:11.590 回答
0

我的替代尝试,很大程度上依赖于这样一个事实,即当转换为 yaml 时,空替代最终将成为文本,即:{cluster = <static | web>.static}被解释为cluster: static

这意味着,我可以即:

let Clusters = < bodhi_static | bodhi_web >

let Route =
      { Type = { match : { prefix : Text }, cluster : Clusters }
      , default = {=}
      }

let Cluster = { Type = { name : Clusters }, default = {=} }

in  { matches =
        [ Route::{ match = { prefix = "/" }, cluster = Clusters.bodhi_web }
        , Route::{
          , match = { prefix = "/static" }
          , cluster = Clusters.bodhi_static
          }
        ]
    , clusters =
        [ Cluster::{ name = Clusters.bodhi_static }
        , Cluster::{ name = Clusters.bodhi_web }
        ]
    }

更多重复,但更简单的imo?

于 2019-12-13T16:21:22.697 回答