Add package.dhall (#95)

* Add a `package.dhall` file, which re-exports `schemas.dhall` and adds
`IntOrString`. The expected hash of `package.dhall` is currently:
sha256:3ea8628b704704de295261dfc7626c15247c589c10a266f970cade262543fdda

* Update documentation and examples to clarify that expected usage is
through the `package.dhall` file.

* README.md cleanup: Update tutorial reference URL to the latest `1.28`
release of `dhall-haskell`, and change code language hints from
`haskell` to `dhall`.
This commit is contained in:
Ari Becker 2019-12-07 23:41:54 +02:00 committed by Gabriel Gonzalez
parent 7af2ab5345
commit bbfec3d854
8 changed files with 167 additions and 157 deletions

View File

@ -38,26 +38,22 @@ or the [full tutorial][dhall-tutorial].
Let's say we'd like to configure a Deployment exposing an `nginx` webserver. Let's say we'd like to configure a Deployment exposing an `nginx` webserver.
In the following example, we: In the following example, we:
1. Import the Kubernetes definitions as Dhall Types (the `types.dhall` file) from the local repo. 1. Import the Kubernetes definitions as a Dhall package (the `package.dhall` file) from the local repo.
In your case you will want to replace the local path with a remote one, e.g. In your case you will want to replace the local path with a remote one, e.g.
`https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/0a4f0b87fbdd4b679853c81ff804bde7b44336cf/types.dhall`. `https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/master/package.dhall`
Note: the `sha256:..` is applied to some imports so that: Note: the `sha256:..` is applied to some imports so that:
1. the import is cached locally after the first evaluation, with great time savings (and avoiding network calls) 1. the import is cached locally after the first evaluation, with great time savings (and avoiding network calls)
2. prevent execution if the content of the file changes. This is a security feature, and you 2. prevent execution if the content of the file changes. This is a security feature, and you
can read more [in Dhall's "Security Guarantees" document][security-hashes] can read more [in Dhall's "Security Guarantees" document][security-hashes]
2. Import the defaults for the above types. Note: instead of using the `package.dhall` from the `master` branch, you may want to use a tagged release,
Since _most_ of the fields in any definition are optional, for better ergonomics while as the contents of the `master` branch are liable to change without warning.
coding Dhall we have generated default values for all types, so we can just use the `//` 2. Define the [Deployment][deployment] using the schema pattern and hardcoding the deployment details:
operator (right-biased record merge) to add our data to the default configuration.
The pattern looks something like this: `defaultValue // { ourDataHere = ..}`
3. Define the [Deployment][deployment] using this pattern (see the default [here][default-deployment])
and hardcoding the deployment details:
```haskell ```dhall
-- examples/deploymentSimple.dhall -- examples/deploymentSimple.dhall
let kubernetes = let kubernetes =
../schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785 ../package.dhall sha256:3ea8628b704704de295261dfc7626c15247c589c10a266f970cade262543fdda
let deployment = let deployment =
kubernetes.Deployment::{ kubernetes.Deployment::{
@ -134,7 +130,7 @@ and reuse those objects for configuring other things (e.g. configuring the servi
templating documentation, configuring Terraform deployments, you name it). templating documentation, configuring Terraform deployments, you name it).
As an example of that, next we'll define an Ingress (an [Nginx Ingress][nginx-ingress] in this case), As an example of that, next we'll define an Ingress (an [Nginx Ingress][nginx-ingress] in this case),
containing stuff like TLS certs and routes for every service - see the [type][Ingress] and [default][Ingress-default] for it. containing stuff like TLS certs and routes for every service - see the [schema][Ingress].
Things to note in the following example: Things to note in the following example:
- we define the `Service` type inline in the file, but in your case you'll want to have a - we define the `Service` type inline in the file, but in your case you'll want to have a
@ -145,7 +141,7 @@ Things to note in the following example:
`mkIngress` function instead of applying it, so you can do something like `mkIngress` function instead of applying it, so you can do something like
`dhall-to-yaml --omitEmpty <<< "./mkIngress.dhall ./myServices.dhall"` `dhall-to-yaml --omitEmpty <<< "./mkIngress.dhall ./myServices.dhall"`
```haskell ```dhall
-- examples/ingress.dhall -- examples/ingress.dhall
let Prelude = ../Prelude.dhall let Prelude = ../Prelude.dhall
@ -154,25 +150,22 @@ let map = Prelude.List.map
let kv = Prelude.JSON.keyText let kv = Prelude.JSON.keyText
let types =
../types.dhall sha256:e48e21b807dad217a6c3e631fcaf3e950062310bfb4a8bbcecc330eb7b2f60ed
let kubernetes = let kubernetes =
../schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785 ../package.dhall sha256:3ea8628b704704de295261dfc7626c15247c589c10a266f970cade262543fdda
let Service = { name : Text, host : Text, version : Text } let Service = { name : Text, host : Text, version : Text }
let services = [ { name = "foo", host = "foo.example.com", version = "2.3" } ] let services = [ { name = "foo", host = "foo.example.com", version = "2.3" } ]
let makeTLS let makeTLS
: Service → types.IngressTLS : Service → kubernetes.IngressTLS.Type
= λ(service : Service) = λ(service : Service)
→ { hosts = [ service.host ] → { hosts = [ service.host ]
, secretName = Some "${service.name}-certificate" , secretName = Some "${service.name}-certificate"
} }
let makeRule let makeRule
: Service → types.IngressRule : Service → kubernetes.IngressRule.Type
= λ(service : Service) = λ(service : Service)
→ { host = Some service.host → { host = Some service.host
, http = , http =
@ -180,7 +173,7 @@ let makeRule
{ paths = { paths =
[ { backend = [ { backend =
{ serviceName = service.name { serviceName = service.name
, servicePort = types.IntOrString.Int 80 , servicePort = kubernetes.IntOrString.Int 80
} }
, path = None Text , path = None Text
} }
@ -189,7 +182,7 @@ let makeRule
} }
let mkIngress let mkIngress
: List Service → types.Ingress : List Service → kubernetes.Ingress.Type
= λ(inputServices : List Service) = λ(inputServices : List Service)
→ let annotations = → let annotations =
[ kv "kubernetes.io/ingress.class" "nginx" [ kv "kubernetes.io/ingress.class" "nginx"
@ -206,8 +199,14 @@ let mkIngress
let spec = let spec =
kubernetes.IngressSpec::{ kubernetes.IngressSpec::{
, tls = map Service types.IngressTLS makeTLS ingressServices , tls =
, rules = map Service types.IngressRule makeRule ingressServices map Service kubernetes.IngressTLS.Type makeTLS ingressServices
, rules =
map
Service
kubernetes.IngressRule.Type
makeRule
ingressServices
} }
in kubernetes.Ingress::{ in kubernetes.Ingress::{
@ -284,7 +283,7 @@ it's possible to use it together with the [union type of all k8s types that we g
So if we want to deploy e.g. a Deployment and a Service together, we can do: So if we want to deploy e.g. a Deployment and a Service together, we can do:
```haskell ```dhall
let k8s = ./typesUnion.dhall let k8s = ./typesUnion.dhall
in in
@ -344,10 +343,8 @@ to run this command afterwards.
[kubernetes]: https://kubernetes.io/ [kubernetes]: https://kubernetes.io/
[normalization]: https://en.wikipedia.org/wiki/Normalization_property_(abstract_rewriting) [normalization]: https://en.wikipedia.org/wiki/Normalization_property_(abstract_rewriting)
[nginx-ingress]: https://github.com/kubernetes/ingress-nginx [nginx-ingress]: https://github.com/kubernetes/ingress-nginx
[dhall-tutorial]: http://hackage.haskell.org/package/dhall-1.21.0/docs/Dhall-Tutorial.html [dhall-tutorial]: http://hackage.haskell.org/package/dhall-1.28.0/docs/Dhall-Tutorial.html
[default-deployment]: ./defaults/io.k8s.api.apps.v1.Deployment.dhall [deployment]: ./schemas/io.k8s.api.apps.v1.Deployment.dhall
[deployment]: ./types/io.k8s.api.apps.v1.Deployment.dhall [Ingress]: ./schemas/io.k8s.api.extensions.v1beta1.Ingress.dhall
[Ingress]: ./types/io.k8s.api.extensions.v1beta1.Ingress.dhall
[Ingress-default]: ./default/io.k8s.api.extensions.v1beta1.Ingress.dhall
[prometheus-operator]: https://github.com/coreos/prometheus-operator [prometheus-operator]: https://github.com/coreos/prometheus-operator
[dhall-prometheus-operator]: https://github.com/coralogix/dhall-prometheus-operator [dhall-prometheus-operator]: https://github.com/coralogix/dhall-prometheus-operator

View File

@ -39,22 +39,18 @@ or the [full tutorial][dhall-tutorial].
Let's say we'd like to configure a Deployment exposing an `nginx` webserver. Let's say we'd like to configure a Deployment exposing an `nginx` webserver.
In the following example, we: In the following example, we:
1. Import the Kubernetes definitions as Dhall Types (the `types.dhall` file) from the local repo. 1. Import the Kubernetes definitions as a Dhall package (the `package.dhall` file) from the local repo.
In your case you will want to replace the local path with a remote one, e.g. In your case you will want to replace the local path with a remote one, e.g.
`https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/0a4f0b87fbdd4b679853c81ff804bde7b44336cf/types.dhall`. `https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/master/package.dhall`
Note: the `sha256:..` is applied to some imports so that: Note: the `sha256:..` is applied to some imports so that:
1. the import is cached locally after the first evaluation, with great time savings (and avoiding network calls) 1. the import is cached locally after the first evaluation, with great time savings (and avoiding network calls)
2. prevent execution if the content of the file changes. This is a security feature, and you 2. prevent execution if the content of the file changes. This is a security feature, and you
can read more [in Dhall's "Security Guarantees" document][security-hashes] can read more [in Dhall's "Security Guarantees" document][security-hashes]
2. Import the defaults for the above types. Note: instead of using the `package.dhall` from the `master` branch, you may want to use a tagged release,
Since _most_ of the fields in any definition are optional, for better ergonomics while as the contents of the `master` branch are liable to change without warning.
coding Dhall we have generated default values for all types, so we can just use the `//` 2. Define the [Deployment][deployment] using the schema pattern and hardcoding the deployment details:
operator (right-biased record merge) to add our data to the default configuration.
The pattern looks something like this: `defaultValue // { ourDataHere = ..}`
3. Define the [Deployment][deployment] using this pattern (see the default [here][default-deployment])
and hardcoding the deployment details:
```haskell ```dhall
-- examples/deploymentSimple.dhall -- examples/deploymentSimple.dhall
${../examples/deploymentSimple.dhall as Text} ${../examples/deploymentSimple.dhall as Text}
@ -87,7 +83,7 @@ and reuse those objects for configuring other things (e.g. configuring the servi
templating documentation, configuring Terraform deployments, you name it). templating documentation, configuring Terraform deployments, you name it).
As an example of that, next we'll define an Ingress (an [Nginx Ingress][nginx-ingress] in this case), As an example of that, next we'll define an Ingress (an [Nginx Ingress][nginx-ingress] in this case),
containing stuff like TLS certs and routes for every service - see the [type][Ingress] and [default][Ingress-default] for it. containing stuff like TLS certs and routes for every service - see the [schema][Ingress].
Things to note in the following example: Things to note in the following example:
- we define the `Service` type inline in the file, but in your case you'll want to have a - we define the `Service` type inline in the file, but in your case you'll want to have a
@ -98,7 +94,7 @@ Things to note in the following example:
`mkIngress` function instead of applying it, so you can do something like `mkIngress` function instead of applying it, so you can do something like
`dhall-to-yaml --omitEmpty <<< "./mkIngress.dhall ./myServices.dhall"` `dhall-to-yaml --omitEmpty <<< "./mkIngress.dhall ./myServices.dhall"`
```haskell ```dhall
-- examples/ingress.dhall -- examples/ingress.dhall
${../examples/ingress.dhall as Text} ${../examples/ingress.dhall as Text}
@ -137,7 +133,7 @@ it's possible to use it together with the [union type of all k8s types that we g
So if we want to deploy e.g. a Deployment and a Service together, we can do: So if we want to deploy e.g. a Deployment and a Service together, we can do:
```haskell ```dhall
let k8s = ./typesUnion.dhall let k8s = ./typesUnion.dhall
in in
@ -197,11 +193,9 @@ to run this command afterwards.
[kubernetes]: https://kubernetes.io/ [kubernetes]: https://kubernetes.io/
[normalization]: https://en.wikipedia.org/wiki/Normalization_property_(abstract_rewriting) [normalization]: https://en.wikipedia.org/wiki/Normalization_property_(abstract_rewriting)
[nginx-ingress]: https://github.com/kubernetes/ingress-nginx [nginx-ingress]: https://github.com/kubernetes/ingress-nginx
[dhall-tutorial]: http://hackage.haskell.org/package/dhall-1.21.0/docs/Dhall-Tutorial.html [dhall-tutorial]: http://hackage.haskell.org/package/dhall-1.28.0/docs/Dhall-Tutorial.html
[default-deployment]: ./defaults/io.k8s.api.apps.v1.Deployment.dhall [deployment]: ./schemas/io.k8s.api.apps.v1.Deployment.dhall
[deployment]: ./types/io.k8s.api.apps.v1.Deployment.dhall [Ingress]: ./schemas/io.k8s.api.extensions.v1beta1.Ingress.dhall
[Ingress]: ./types/io.k8s.api.extensions.v1beta1.Ingress.dhall
[Ingress-default]: ./default/io.k8s.api.extensions.v1beta1.Ingress.dhall
[prometheus-operator]: https://github.com/coreos/prometheus-operator [prometheus-operator]: https://github.com/coreos/prometheus-operator
[dhall-prometheus-operator]: https://github.com/coralogix/dhall-prometheus-operator [dhall-prometheus-operator]: https://github.com/coralogix/dhall-prometheus-operator
'' ''

View File

@ -1,4 +1,5 @@
let kubernetes = ../schemas.dhall let kubernetes =
../package.dhall sha256:3ea8628b704704de295261dfc7626c15247c589c10a266f970cade262543fdda
let release = "wintering-rodent" let release = "wintering-rodent"
@ -13,92 +14,108 @@ let chart = "${name}-${version}"
let heritage = "dhall" let heritage = "dhall"
in kubernetes.DaemonSet::{ in kubernetes.DaemonSet::{
, metadata = kubernetes.ObjectMeta::{ , metadata =
, name = fullName kubernetes.ObjectMeta::{
, labels = toMap , name = fullName
{ app = name , labels =
, chart = chart toMap
, release = release { app = name
, heritage = heritage , chart = chart
, release = release
, heritage = heritage
}
} }
} , spec =
, spec = Some kubernetes.DaemonSetSpec::{ Some
, updateStrategy = Some kubernetes.DaemonSetUpdateStrategy::{ kubernetes.DaemonSetSpec::{
, type = Some "RollingUpdate" , updateStrategy =
} Some
, template = kubernetes.PodTemplateSpec::{ kubernetes.DaemonSetUpdateStrategy::{
, metadata = kubernetes.ObjectMeta::{ , type = Some "RollingUpdate"
, name = name }
, annotations = toMap , template =
{ `scheduler.alpha.kubernetes.io/critical-pod` = "" kubernetes.PodTemplateSpec::{
} , metadata =
, labels = toMap kubernetes.ObjectMeta::{
{ app = name , name = name
, release = release , annotations =
} toMap
{ `scheduler.alpha.kubernetes.io/critical-pod` = "" }
, labels = toMap { app = name, release = release }
}
, spec =
Some
kubernetes.PodSpec::{
, hostNetwork = Some True
, nodeSelector =
toMap { `node-role.kubernetes.io/master` = "" }
, tolerations =
[ kubernetes.Toleration::{
, effect = Some "NoSchedule"
, key = Some "node-role.kubernetes.io/master"
}
, kubernetes.Toleration::{
, effect = Some "CriticalAddonsOnly"
, key = Some "Exists"
}
]
, containers =
[ kubernetes.Container::{
, name = fullName
, image =
Some "gcr.io/heptio-images/authenticator:v0.1.0"
, args =
[ "server"
, "--config=/etc/aws-iam-authenticator/config.yaml"
, "--state-dir=/var/aws-iam-authenticator"
, "--generate-kubeconfig=/etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml"
]
, volumeMounts =
[ kubernetes.VolumeMount::{
, name = "config"
, mountPath = "/etc/aws-iam-authenticator/"
}
, kubernetes.VolumeMount::{
, name = "state"
, mountPath = "/var/aws-iam-authenticator/"
}
, kubernetes.VolumeMount::{
, name = "output"
, mountPath =
"/etc/kubernetes/aws-iam-authenticator/"
}
]
}
]
, volumes =
[ kubernetes.Volume::{
, name = "config"
, configMap =
Some
kubernetes.ConfigMapVolumeSource::{
, name = Some fullName
}
}
, kubernetes.Volume::{
, name = "output"
, hostPath =
Some
kubernetes.HostPathVolumeSource::{
, path =
"/srv/kubernetes/aws-iam-authenticator/"
}
}
, kubernetes.Volume::{
, name = "state"
, hostPath =
Some
kubernetes.HostPathVolumeSource::{
, path =
"/srv/kubernetes/aws-iam-authenticator/"
}
}
]
}
}
} }
, spec = Some kubernetes.PodSpec::{
, hostNetwork = Some True
, nodeSelector = toMap
{ `node-role.kubernetes.io/master` = ""
}
, tolerations =
[ kubernetes.Toleration::{
, effect = Some "NoSchedule"
, key = Some "node-role.kubernetes.io/master"
}
, kubernetes.Toleration::{
, effect = Some "CriticalAddonsOnly"
, key = Some "Exists"
}
]
, containers =
[ kubernetes.Container::{
, name = fullName
, image = Some "gcr.io/heptio-images/authenticator:v0.1.0"
, args =
[ "server"
, "--config=/etc/aws-iam-authenticator/config.yaml"
, "--state-dir=/var/aws-iam-authenticator"
, "--generate-kubeconfig=/etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml"
]
, volumeMounts =
[ kubernetes.VolumeMount::{
, name = "config"
, mountPath = "/etc/aws-iam-authenticator/"
}
, kubernetes.VolumeMount::{
, name = "state"
, mountPath = "/var/aws-iam-authenticator/"
}
, kubernetes.VolumeMount::{
, name = "output"
, mountPath = "/etc/kubernetes/aws-iam-authenticator/"
}
]
}
]
, volumes =
[ kubernetes.Volume::{
, name = "config"
, configMap = Some kubernetes.ConfigMapVolumeSource::{
, name = Some fullName
}
}
, kubernetes.Volume::{
, name = "output"
, hostPath = Some kubernetes.HostPathVolumeSource::{
, path = "/srv/kubernetes/aws-iam-authenticator/"
}
}
, kubernetes.Volume::{
, name = "state"
, hostPath = Some kubernetes.HostPathVolumeSource::{
, path = "/srv/kubernetes/aws-iam-authenticator/"
}
}
]
}
}
}
} }

View File

@ -1,8 +1,5 @@
let types =
../types.dhall sha256:e48e21b807dad217a6c3e631fcaf3e950062310bfb4a8bbcecc330eb7b2f60ed
let kubernetes = let kubernetes =
../schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785 ../package.dhall sha256:3ea8628b704704de295261dfc7626c15247c589c10a266f970cade262543fdda
let kv = (../Prelude.dhall).JSON.keyText let kv = (../Prelude.dhall).JSON.keyText
@ -21,8 +18,8 @@ let deployment =
kubernetes.DeploymentStrategy::{ kubernetes.DeploymentStrategy::{
, type = Some "RollingUpdate" , type = Some "RollingUpdate"
, rollingUpdate = , rollingUpdate =
{ maxSurge = Some (types.IntOrString.Int 5) { maxSurge = Some (kubernetes.IntOrString.Int 5)
, maxUnavailable = Some (types.IntOrString.Int 0) , maxUnavailable = Some (kubernetes.IntOrString.Int 0)
} }
} }
, template = , template =

View File

@ -1,5 +1,5 @@
let kubernetes = let kubernetes =
../schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785 ../package.dhall sha256:3ea8628b704704de295261dfc7626c15247c589c10a266f970cade262543fdda
let deployment = let deployment =
kubernetes.Deployment::{ kubernetes.Deployment::{

View File

@ -4,25 +4,22 @@ let map = Prelude.List.map
let kv = Prelude.JSON.keyText let kv = Prelude.JSON.keyText
let types =
../types.dhall sha256:e48e21b807dad217a6c3e631fcaf3e950062310bfb4a8bbcecc330eb7b2f60ed
let kubernetes = let kubernetes =
../schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785 ../package.dhall sha256:3ea8628b704704de295261dfc7626c15247c589c10a266f970cade262543fdda
let Service = { name : Text, host : Text, version : Text } let Service = { name : Text, host : Text, version : Text }
let services = [ { name = "foo", host = "foo.example.com", version = "2.3" } ] let services = [ { name = "foo", host = "foo.example.com", version = "2.3" } ]
let makeTLS let makeTLS
: Service → types.IngressTLS : Service → kubernetes.IngressTLS.Type
= λ(service : Service) = λ(service : Service)
→ { hosts = [ service.host ] → { hosts = [ service.host ]
, secretName = Some "${service.name}-certificate" , secretName = Some "${service.name}-certificate"
} }
let makeRule let makeRule
: Service → types.IngressRule : Service → kubernetes.IngressRule.Type
= λ(service : Service) = λ(service : Service)
→ { host = Some service.host → { host = Some service.host
, http = , http =
@ -30,7 +27,7 @@ let makeRule
{ paths = { paths =
[ { backend = [ { backend =
{ serviceName = service.name { serviceName = service.name
, servicePort = types.IntOrString.Int 80 , servicePort = kubernetes.IntOrString.Int 80
} }
, path = None Text , path = None Text
} }
@ -39,7 +36,7 @@ let makeRule
} }
let mkIngress let mkIngress
: List Service → types.Ingress : List Service → kubernetes.Ingress.Type
= λ(inputServices : List Service) = λ(inputServices : List Service)
→ let annotations = → let annotations =
[ kv "kubernetes.io/ingress.class" "nginx" [ kv "kubernetes.io/ingress.class" "nginx"
@ -56,8 +53,14 @@ let mkIngress
let spec = let spec =
kubernetes.IngressSpec::{ kubernetes.IngressSpec::{
, tls = map Service types.IngressTLS makeTLS ingressServices , tls =
, rules = map Service types.IngressRule makeRule ingressServices map Service kubernetes.IngressTLS.Type makeTLS ingressServices
, rules =
map
Service
kubernetes.IngressRule.Type
makeRule
ingressServices
} }
in kubernetes.Ingress::{ in kubernetes.Ingress::{

View File

@ -1,8 +1,5 @@
let types =
../types.dhall sha256:e48e21b807dad217a6c3e631fcaf3e950062310bfb4a8bbcecc330eb7b2f60ed
let kubernetes = let kubernetes =
../schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785 ../package.dhall sha256:3ea8628b704704de295261dfc7626c15247c589c10a266f970cade262543fdda
let kv = (../Prelude.dhall).JSON.keyText let kv = (../Prelude.dhall).JSON.keyText
@ -11,14 +8,14 @@ let spec =
, type = Some "NodePort" , type = Some "NodePort"
, ports = , ports =
[ kubernetes.ServicePort::{ [ kubernetes.ServicePort::{
, targetPort = Some (types.IntOrString.Int 80) , targetPort = Some (kubernetes.IntOrString.Int 80)
, port = 80 , port = 80
} }
] ]
} }
let service let service
: types.Service : kubernetes.Service.Type
= kubernetes.Service::{ = kubernetes.Service::{
, metadata = , metadata =
kubernetes.ObjectMeta::{ kubernetes.ObjectMeta::{

5
package.dhall Normal file
View File

@ -0,0 +1,5 @@
./schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785
∧ { IntOrString =
( ./types.dhall sha256:e48e21b807dad217a6c3e631fcaf3e950062310bfb4a8bbcecc330eb7b2f60ed
).IntOrString
}