dhall-kubernetes/README.md

354 lines
12 KiB
Markdown
Raw Permalink Normal View History

2018-06-02 23:43:49 +03:00
# `dhall-kubernetes`
2017-09-20 17:56:49 +03:00
2019-04-02 12:53:33 +03:00
<img src="logo/dhall-kubernetes-logo.svg" alt="dhall-kubernetes logo" height="300px"/>
`dhall-kubernetes` contains [Dhall][dhall-lang] bindings to [Kubernetes][kubernetes],
so you can generate Kubernetes objects definitions from Dhall expressions.
This will let you easily typecheck, template and modularize your Kubernetes definitions.
## Why do I need this
Once you build a slightly non-trivial Kubernetes setup, with many objects floating
around, you'll encounter several issues:
1. Writing the definitions in YAML is really verbose, and the actually important
things don't stand out that much
2. Ok I have a bunch of objects that'll need to be configured together, how do I share data?
3. I'd like to reuse an object for different environments, but I cannot make it parametric..
4. In general, I'd really love to reuse parts of some definitions in other definitions
5. Oh no, I typoed a key and I had to wait until I pushed to the cluster to get an error back :(
The natural tendency is to reach for a templating language + a programming language to orchestrate that + some more configuration for it...
But this is just really messy (been there), and we can do better.
Dhall solves all of this, being a programming language with builtin templating,
all while being non-Turing complete, strongly typed and [strongly normalizing][normalization]
(i.e.: reduces everything to a normal form, no matter how much abstraction you build),
so saving you from the *"oh-noes-I-made-my-config-in-code-and-now-its-too-abstract"* nightmare.
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
For a Dhall Tutorial, see [the website][dhall-website], or the [readme of the project][dhall-lang],
or the [full tutorial][dhall-tutorial].
2018-06-02 23:43:49 +03:00
## Prerequisites
**NOTE**: `dhall-kubernetes` requires at least version `1.27.0` of [the interpreter](https://github.com/dhall-lang/dhall-haskell)
(version `11.0.0` of the language).
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
## Quickstart - a simple Deployment
2018-06-02 23:43:49 +03:00
Let's say we'd like to configure a Deployment exposing an `nginx` webserver.
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
In the following example, we:
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
1. Import the Kubernetes definitions as Dhall Types (the `types.dhall` file) from the local repo.
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`.
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)
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]
2. Import the defaults for the above types.
Since _most_ of the fields in any definition are optional, for better ergonomics while
coding Dhall we have generated default values for all types, so we can just use the `//`
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:
2018-06-02 23:43:49 +03:00
```haskell
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
-- examples/deploymentSimple.dhall
let kubernetes =
../schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785
let deployment =
kubernetes.Deployment::{
, metadata = kubernetes.ObjectMeta::{ name = "nginx" }
, spec =
Some
kubernetes.DeploymentSpec::{
, replicas = Some 2
, template =
kubernetes.PodTemplateSpec::{
, metadata = kubernetes.ObjectMeta::{ name = "nginx" }
, spec =
Some
kubernetes.PodSpec::{
, containers =
[ kubernetes.Container::{
, name = "nginx"
, image = Some "nginx:1.15.3"
, ports =
[ kubernetes.ContainerPort::{
, containerPort = 80
}
]
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
}
]
}
}
}
}
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
in deployment
2018-06-02 23:43:49 +03:00
```
We then run this through `dhall-to-yaml` to generate our Kubernetes definition:
2017-09-20 18:24:48 +03:00
2017-09-20 17:56:49 +03:00
```bash
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
dhall-to-yaml --omitEmpty < examples/deploymentSimple.dhall
2018-06-02 23:43:49 +03:00
```
And we get:
```yaml
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
## examples/out/deploymentSimple.yaml
apiVersion: apps/v1
2018-06-02 23:43:49 +03:00
kind: Deployment
metadata:
name: nginx
2018-06-02 23:43:49 +03:00
spec:
replicas: 2
2018-06-02 23:43:49 +03:00
template:
metadata:
name: nginx
spec:
containers:
- image: nginx:1.15.3
name: nginx
ports:
- containerPort: 80
2017-09-20 18:24:48 +03:00
```
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
## More modular: defining an Ingress
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
The above is cool, but hardcoding data is not that cool.
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
So in a more realistic deployment you'll probably want to define:
- some `MyService` type that contains the config settings relevant to your deployments
- some functions parametrized by this type, so that you can produce objects to send to k8s
by just applying these functions to `MyService` objects
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
This is useful because then you can define your `Service`s separately from the Kubernetes logic,
and reuse those objects for configuring other things (e.g. configuring the services themselves,
templating documentation, configuring Terraform deployments, you name it).
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
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.
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
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
separate `./Service.dhall` file (so you can share around the project)
- we define functions to create the TLS definitions and the routes, so that we can `map`
them over the list of services.
- we also defined the list of `services` inline, but you should instead return the
`mkIngress` function instead of applying it, so you can do something like
`dhall-to-yaml --omitEmpty <<< "./mkIngress.dhall ./myServices.dhall"`
2018-06-02 23:43:49 +03:00
```haskell
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
-- examples/ingress.dhall
let Prelude = ../Prelude.dhall
let map = Prelude.List.map
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
let kv = Prelude.JSON.keyText
let types =
2019-07-30 10:25:00 +03:00
../types.dhall sha256:e48e21b807dad217a6c3e631fcaf3e950062310bfb4a8bbcecc330eb7b2f60ed
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
let kubernetes =
../schemas.dhall sha256:9704063d1e2d17050cb18afae199a24f4cd1264e6c8e696ca94781309e213785
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
let Service = { name : Text, host : Text, version : Text }
let services = [ { name = "foo", host = "foo.example.com", version = "2.3" } ]
let makeTLS
: Service → types.IngressTLS
= λ(service : Service)
→ { hosts = [ service.host ]
, secretName = Some "${service.name}-certificate"
}
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
let makeRule
: Service → types.IngressRule
= λ(service : Service)
→ { host = Some service.host
, http =
Some
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
{ paths =
[ { backend =
{ serviceName = service.name
, servicePort = types.IntOrString.Int 80
2018-11-12 21:24:18 +03:00
}
, path = None Text
2018-11-12 21:24:18 +03:00
}
]
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
}
}
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
let mkIngress
: List Service → types.Ingress
= λ(inputServices : List Service)
→ let annotations =
[ kv "kubernetes.io/ingress.class" "nginx"
, kv "kubernetes.io/ingress.allow-http" "false"
]
let defaultService =
{ name = "default"
, host = "default.example.com"
, version = " 1.0"
}
let ingressServices = inputServices # [ defaultService ]
let spec =
kubernetes.IngressSpec::{
, tls = map Service types.IngressTLS makeTLS ingressServices
, rules = map Service types.IngressRule makeRule ingressServices
}
in kubernetes.Ingress::{
, metadata =
kubernetes.ObjectMeta::{
, name = "nginx"
, annotations = annotations
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
}
, spec = Some spec
}
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
in mkIngress services
2018-06-02 23:43:49 +03:00
```
As before we get the yaml out by running:
2018-06-02 23:43:49 +03:00
```bash
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
dhall-to-yaml --omitEmpty < examples/ingress.dhall
2017-09-20 18:24:48 +03:00
```
2018-06-02 23:43:49 +03:00
Result:
2018-06-02 23:43:49 +03:00
```yaml
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
## examples/out/ingress.yaml
2019-07-30 10:25:00 +03:00
apiVersion: networking.k8s.io/v1beta1
2018-06-02 23:43:49 +03:00
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.allow-http: "false"
2018-06-02 23:43:49 +03:00
kubernetes.io/ingress.class: nginx
name: nginx
spec:
rules:
- host: foo.example.com
http:
paths:
- backend:
serviceName: foo
servicePort: 80
- host: default.example.com
http:
paths:
- backend:
serviceName: default
servicePort: 80
tls:
- hosts:
- foo.example.com
secretName: foo-certificate
- hosts:
- default.example.com
secretName: default-certificate
2017-09-20 17:56:49 +03:00
```
2018-06-02 23:43:49 +03:00
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
## FAQ
#### Can I generate a YAML file with many objects in it?
It is usual for k8s YAML files to include multiple objects separated by `---` ("documents" in YAML lingo),
so you might want to do it too.
If the objects have the same type, this is very easy: you return a Dhall list containing the
objects, and use the `--documents` flag, e.g.:
```bash
dhall-to-yaml --documents --omitEmpty <<< "let a = ./examples/deploymentSimple.dhall in [a, a]"
```
If the objects are of different type, it's not possible to have separate documents in the same YAML file.
However, since [k8s has a builtin `List` type for these cases](https://github.com/kubernetes/kubernetes/blob/master/hack/testdata/list.yaml),
it's possible to use it together with the [union type of all k8s types that we generate][typesUnion].
So if we want to deploy e.g. a Deployment and a Service together, we can do:
```haskell
let k8s = ./typesUnion.dhall
in
{ apiVersion = "v1"
, kind = "List"
, items =
[ k8s.Deployment ./my-deployment.dhall
, k8s.Service ./my-service.dhall
]
}
```
## Projects Using `dhall-kubernetes`
* [dhall-prometheus-operator][dhall-prometheus-operator]: Provides types and default records for [Prometheus Operators][prometheus-operator].
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
## Development
### Updating the nixpkgs snapshot (and kubernetes version)
Run
```bash
./scripts/update-nixpkgs.sh
./generate.sh
```
If the tests fail, rollback. If they don't then you have sucessfully upgraded!
### Tests
All tests are defined in `release.nix`. We run these tests in CI in a [Hydra
project][hydra-project].
You can run the tests locally with the following command:
```bash
nix build --file ./release.nix
```
### Generating `types` `default` and `README.md`
Running `scripts/generate.sh` will generate all dhall files from the kubernetes
swagger specification, and copy them to `types` and `default`. It will also
generate `README.md` from `docs/README.md.dhall`.
If you make changes to `scripts/convert.py` or `docs/README.md.dhall`, you need
to run this command afterwards.
2019-05-02 10:29:02 +03:00
[stack]: https://haskellstack.org/
[hydra-project]: http://hydra.dhall-lang.org/project/dhall-kubernetes
2018-06-02 23:43:49 +03:00
[dhall-lang]: https://github.com/dhall-lang/dhall-lang
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
[dhall-website]: https://dhall-lang.org/
[security-hashes]: https://github.com/dhall-lang/dhall-lang/wiki/Safety-guarantees#code-injection
[typesUnion]: https://github.com/dhall-lang/dhall-kubernetes/blob/master/typesUnion.dhall
[kubernetes]: https://kubernetes.io/
[normalization]: https://en.wikipedia.org/wiki/Normalization_property_(abstract_rewriting)
[nginx-ingress]: https://github.com/kubernetes/ingress-nginx
API v2 (#57) This ports the conversion script from Python to Haskell (fix #7) The main reasons for this port are that: - the Python script was really hard to maintain for reasons like "converting from Swagger to Dhall is interleaved with string formatting" - in Haskell we can use the dhall library to generate always syntactically correct Dhall AST. It's also much easier to keep an eye on correctness, because types and pattern matching. It also forces us to deal with things like cyclic imports from the get go. Things happening here: - remove the `api` folder, removing the difference between "raw api" and "nice api" - move defaults from `default` to `defaults` folder, as it is in `dhall-nethack` - transition to the new syntax for `Optional` (fix #49) - add `types.dhall` and `defaults.dhall`, so that one can now easily "pin a version" by just importing these two records at a specific commit/tag. They also make it really easy to access objects, e.g. `let types = https://raw.githubusercontent... sha256:... in types.Deployment` - also add typesUnion.dhall (fix #54), so one is able to send to Kubernetes different objects in the same stream. This is also documented in the README - defaults are resolved recursively (fix #46): if there's an import of a "nullable" record, then it's not marked as Optional, making merging objects much easier - default objects are not lambdas anymore, and instead they just don't include the required fields (that is, the ones that are not nullable records), as suggested in dhall-lang/dhall-lang#382 - for objects that are simple types we used to generate a simple lambda `\(a : Text) -> a` as a default, now we just don't generate a default (e.g. see `io.k8s.apimachinery.pkg.apis.meta.v1.Time`) - autoformat all generated Dhall code - remove cyclic imports (fix #47) - update to dhall-1.22 and dhall-json-1.2.8
2019-05-01 19:13:18 +03:00
[dhall-tutorial]: http://hackage.haskell.org/package/dhall-1.21.0/docs/Dhall-Tutorial.html
[default-deployment]: ./defaults/io.k8s.api.apps.v1.Deployment.dhall
[deployment]: ./types/io.k8s.api.apps.v1.Deployment.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
[dhall-prometheus-operator]: https://github.com/coralogix/dhall-prometheus-operator