From 2ed2ffd073de6569014779284b61e4f5824de987 Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Tue, 23 Mar 2021 11:32:34 -0700 Subject: [PATCH] Improve user experience for generating files (#165) This improves the documentation and scripts responsible for generating files. The main changes from the user's point of view are: * The `generate` script now supports four subcommands: * `generate kubernetes` - Generate all Kubernetes bindings * `generate examples` - Generate examples for the preferred Kubernetes version * `generate readme` - Generate the README from the Dhall template * `generate preferred` - Generate top-level files that re-export the preferred Kubernetes version The `generate` script without arguments generates everything * Generation should be faster and more incremental now For example, regenerating the `README` by itself should go more quickly since it no longer requires regenerating any examples or Kubernetes bindings if they haven't changed This required overhauling the internal Nix code for generating these files to support more granular builds. Another consequence of this change is that the preferred Kubernetes version no longer packages `Prelude.dhall`, `README.dhall` or the `examples`. Those are now only stored within the top-level directory. --- 1.17/Prelude.dhall | 29 -- 1.17/README.md | 413 ------------------ .../aws-iam-authenticator-chart.dhall | 98 ----- 1.17/examples/deployment.dhall | 47 -- 1.17/examples/deploymentSimple.dhall | 28 -- 1.17/examples/ingress.dhall | 79 ---- .../out/aws-iam-authenticator-chart.yaml | 58 --- 1.17/examples/out/deployment.yaml | 32 -- 1.17/examples/out/deploymentSimple.yaml | 18 - 1.17/examples/out/ingress.yaml | 28 -- 1.17/examples/out/service.yaml | 13 - 1.17/examples/service.dhall | 28 -- README.md | 108 +++-- docs/README.md.dhall | 108 +++-- nix/dhall-kubernetes.nix | 4 +- nix/nixpkgs.json | 10 +- nix/nixpkgs.nix | 188 ++++---- release.nix | 2 + ...etes-release.sh => add-kubernetes-release} | 2 +- scripts/generate | 71 +++ scripts/generate.sh | 32 -- 21 files changed, 319 insertions(+), 1077 deletions(-) delete mode 100644 1.17/Prelude.dhall delete mode 100644 1.17/README.md delete mode 100644 1.17/examples/aws-iam-authenticator-chart.dhall delete mode 100644 1.17/examples/deployment.dhall delete mode 100644 1.17/examples/deploymentSimple.dhall delete mode 100644 1.17/examples/ingress.dhall delete mode 100644 1.17/examples/out/aws-iam-authenticator-chart.yaml delete mode 100644 1.17/examples/out/deployment.yaml delete mode 100644 1.17/examples/out/deploymentSimple.yaml delete mode 100644 1.17/examples/out/ingress.yaml delete mode 100644 1.17/examples/out/service.yaml delete mode 100644 1.17/examples/service.dhall rename scripts/{add-kubernetes-release.sh => add-kubernetes-release} (82%) create mode 100755 scripts/generate delete mode 100755 scripts/generate.sh diff --git a/1.17/Prelude.dhall b/1.17/Prelude.dhall deleted file mode 100644 index c28d11b3..00000000 --- a/1.17/Prelude.dhall +++ /dev/null @@ -1,29 +0,0 @@ -{- This file provides a central `Prelude` import for the rest of the library to - use so that the integrity check only needs to be updated in one place - whenever upgrading the interpreter. - - This allows the user to provide their own Prelude import using the - `DHALL_PRELUDE` environment variable, like this: - - ``` - $ export DHALL_PRELUDE='https://prelude.dhall-lang.org/package.dhall sha256:...' - ``` - - Note that overriding the Prelude in this way only works if this repository - is imported locally. Remote imports do not have access to environment - variables and any attempt to import one will fall back to the next available - import. To learn more, read: - - * https://docs.dhall-lang.org/discussions/Safety-guarantees.html#cross-site-scripting-xss - - This file also provides an import without the integrity check as a slower - fallback if the user is using a different version of the Dhall interpreter. - - This pattern is documented in the dhall-nethack repo: - - * https://github.com/dhall-lang/dhall-nethack/blob/master/Prelude.dhall --} - - env:DHALL_PRELUDE -? https://raw.githubusercontent.com/dhall-lang/dhall-lang/v17.0.0/Prelude/package.dhall sha256:10db3c919c25e9046833df897a8ffe2701dc390fa0893d958c3430524be5a43e -? https://raw.githubusercontent.com/dhall-lang/dhall-lang/v17.0.0/Prelude/package.dhall diff --git a/1.17/README.md b/1.17/README.md deleted file mode 100644 index e65dd619..00000000 --- a/1.17/README.md +++ /dev/null @@ -1,413 +0,0 @@ -# `dhall-kubernetes` - -dhall-kubernetes logo - -`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. - -For a Dhall Tutorial, see [the website][dhall-website], or the [readme of the project][dhall-lang], -or the [full tutorial][dhall-tutorial]. - -## 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). - -## Quickstart - a simple Deployment - -Let's say we'd like to configure a Deployment exposing an `nginx` webserver. - -In the following example, we: -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. - `https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/master/package.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] - Note: instead of using the `package.dhall` from the `master` branch, you may want to use a tagged release, - as the contents of the `master` branch are liable to change without warning. -2. Define the [Deployment][deployment] using the schema pattern and hardcoding the deployment details: - -```dhall --- examples/deploymentSimple.dhall - -let kubernetes = - https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/master/package.dhall sha256:532e110f424ea8a9f960a13b2ca54779ddcac5d5aa531f86d82f41f8f18d7ef1 - -let deployment = - kubernetes.Deployment::{ - , metadata = kubernetes.ObjectMeta::{ name = Some "nginx" } - , spec = Some kubernetes.DeploymentSpec::{ - , selector = kubernetes.LabelSelector::{ - , matchLabels = Some (toMap { name = "nginx" }) - } - , replicas = Some +2 - , template = kubernetes.PodTemplateSpec::{ - , metadata = Some kubernetes.ObjectMeta::{ name = Some "nginx" } - , spec = Some kubernetes.PodSpec::{ - , containers = - [ kubernetes.Container::{ - , name = "nginx" - , image = Some "nginx:1.15.3" - , ports = Some - [ kubernetes.ContainerPort::{ containerPort = +80 } ] - } - ] - } - } - } - } - -in deployment - -``` - -We then run this through `dhall-to-yaml` to generate our Kubernetes definition: - -```bash -dhall-to-yaml <<< ./examples/deploymentSimple.dhall -``` - -And we get: -```yaml -## examples/out/deploymentSimple.yaml - -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx -spec: - replicas: 2 - selector: - matchLabels: - name: nginx - template: - metadata: - name: nginx - spec: - containers: - - image: nginx:1.15.3 - name: nginx - ports: - - containerPort: 80 - -``` - -## More modular: defining an Ingress - -The above is cool, but hardcoding data is not that cool. - -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 - -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). - -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 [schema][Ingress]. - -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 <<< "./mkIngress.dhall ./myServices.dhall"` - -```dhall --- examples/ingress.dhall - -let Prelude = - ../Prelude.dhall sha256:10db3c919c25e9046833df897a8ffe2701dc390fa0893d958c3430524be5a43e - -let map = Prelude.List.map - -let kubernetes = - https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/master/package.dhall sha256:532e110f424ea8a9f960a13b2ca54779ddcac5d5aa531f86d82f41f8f18d7ef1 - -let Service = { name : Text, host : Text, version : Text } - -let services = [ { name = "foo", host = "foo.example.com", version = "2.3" } ] - -let makeTLS - : Service → kubernetes.IngressTLS.Type - = λ(service : Service) → - { hosts = Some [ service.host ] - , secretName = Some "${service.name}-certificate" - } - -let makeRule - : Service → kubernetes.IngressRule.Type - = λ(service : Service) → - { host = Some service.host - , http = Some - { paths = - [ { backend = - { serviceName = service.name - , servicePort = kubernetes.IntOrString.Int +80 - } - , path = None Text - } - ] - } - } - -let mkIngress - : List Service → kubernetes.Ingress.Type - = λ(inputServices : List Service) → - let annotations = - toMap - { `kubernetes.io/ingress.class` = "nginx" - , `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 = Some - ( map - Service - kubernetes.IngressTLS.Type - makeTLS - ingressServices - ) - , rules = Some - ( map - Service - kubernetes.IngressRule.Type - makeRule - ingressServices - ) - } - - in kubernetes.Ingress::{ - , metadata = kubernetes.ObjectMeta::{ - , name = Some "nginx" - , annotations = Some annotations - } - , spec = Some spec - } - -in mkIngress services - -``` - -As before we get the yaml out by running: - -```bash -dhall-to-yaml <<< ./examples/ingress.dhall -``` - -Result: -```yaml -## examples/out/ingress.yaml - -apiVersion: networking.k8s.io/v1beta1 -kind: Ingress -metadata: - annotations: - kubernetes.io/ingress.allow-http: 'false' - 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 - -``` - -## 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 <<< "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: - -```dhall -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]. - - -## Development - -The logic for generating the Dhall code doesn't reside within this -repository but actually resides within the -[`dhall-openapi`](https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-openapi) -subproject of the [`dhall-haskell`](https://github.com/dhall-lang/dhall-haskell) -repository. That means that if you want to change the generated code you will -need to do so in two steps: - -* Make a pull request against the upstream `dhall-haskell` repository to - change the code generated by `dhall-openapi` - -* Make a pull request against this repository to pick up a newer reference - to the `dhall-haskell` repository incorporating the change to `dhall-openapi` - -If you try to create a pull request to amend the generated Dhall files directly -then CI will reject the pull request since it verifies that the Dhall code -stored in version control matches what `dhall-openapi` would generate from the -Kubernetes OpenAPI specification. - -### Updating the `dhall-openapi` dependency - -The `dhall-openapi` dependency is a subproject of the `dhall-haskell` -repository, so in order to upgrade `dhall-openapi` you need to update the -reference to the `dhall-haskell` repository. - -To upgrade to the latest version of the `dhall-openapi` package, run: - -```bash -nix-prefetch-git --fetch-submodules https://github.com/dhall-lang/dhall-haskell.git > ./nix/dhall-haskell.json -``` - -If you want to build against a local copy of `dhall-haskell`, then edit the -Nix code like this: - -```diff -diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix -index 832ae1a..810e966 100644 ---- a/nix/nixpkgs.nix -+++ b/nix/nixpkgs.nix -@@ -126,11 +126,7 @@ let - json = - builtins.fromJSON (builtins.readFile ./dhall-haskell.json); - -- dhall-haskell = pkgsNew.fetchFromGitHub { -- owner = "dhall-lang"; -- repo = "dhall-haskell"; -- inherit (json) rev sha256 fetchSubmodules; -- }; -+ dhall-haskell = ~/path/to/dhall-haskell; - - in - (import "${dhall-haskell}/default.nix").dhall-openapi; -``` - -### Adding a new Kubernetes releases - -To add a new supported release, run: - -```bash -./scripts/add-kubernetes-release.sh "${VERSION}" -``` - -… and then create a pull request out of the generated files. - -If you want to make a specific release the preferred release, run: - -``` -$ echo "${VERSION}" > ./nix/preferred.txt -$ ./scripts/generate.sh -``` - -### 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 `docs/README.md.dhall`, you need to run this command -afterwards. - - -[stack]: https://haskellstack.org/ -[hydra-project]: http://hydra.dhall-lang.org/project/dhall-kubernetes -[dhall-lang]: https://github.com/dhall-lang/dhall-lang -[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 -[dhall-tutorial]: http://hackage.haskell.org/package/dhall-1.28.0/docs/Dhall-Tutorial.html -[deployment]: ./schemas/io.k8s.api.apps.v1.Deployment.dhall -[Ingress]: ./schemas/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 diff --git a/1.17/examples/aws-iam-authenticator-chart.dhall b/1.17/examples/aws-iam-authenticator-chart.dhall deleted file mode 100644 index 0101a8d6..00000000 --- a/1.17/examples/aws-iam-authenticator-chart.dhall +++ /dev/null @@ -1,98 +0,0 @@ -let kubernetes = - ../package.dhall sha256:532e110f424ea8a9f960a13b2ca54779ddcac5d5aa531f86d82f41f8f18d7ef1 - -let release = "wintering-rodent" - -let name = "aws-iam-authenticator" - -let fullName = "${release}-${name}" - -let version = "0.1.1" - -let chart = "${name}-${version}" - -let heritage = "dhall" - -in kubernetes.DaemonSet::{ - , metadata = kubernetes.ObjectMeta::{ - , name = Some fullName - , labels = Some (toMap { app = name, chart, release, heritage }) - } - , spec = Some kubernetes.DaemonSetSpec::{ - , selector = kubernetes.LabelSelector::{ - , matchLabels = Some (toMap { app = name, release }) - } - , updateStrategy = Some kubernetes.DaemonSetUpdateStrategy::{ - , type = Some "RollingUpdate" - } - , template = kubernetes.PodTemplateSpec::{ - , metadata = Some kubernetes.ObjectMeta::{ - , name = Some name - , annotations = Some - (toMap { `scheduler.alpha.kubernetes.io/critical-pod` = "" }) - , labels = Some (toMap { app = name, release }) - } - , spec = Some kubernetes.PodSpec::{ - , hostNetwork = Some True - , nodeSelector = Some - (toMap { `node-role.kubernetes.io/master` = "" }) - , tolerations = Some - [ 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 = Some - [ "server" - , "--config=/etc/aws-iam-authenticator/config.yaml" - , "--state-dir=/var/aws-iam-authenticator" - , "--generate-kubeconfig=/etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml" - ] - , volumeMounts = Some - [ 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 = Some - [ 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/" - } - } - ] - } - } - } - } diff --git a/1.17/examples/deployment.dhall b/1.17/examples/deployment.dhall deleted file mode 100644 index 4347d060..00000000 --- a/1.17/examples/deployment.dhall +++ /dev/null @@ -1,47 +0,0 @@ -let Prelude = - ../Prelude.dhall sha256:10db3c919c25e9046833df897a8ffe2701dc390fa0893d958c3430524be5a43e - -let kubernetes = - ../package.dhall sha256:532e110f424ea8a9f960a13b2ca54779ddcac5d5aa531f86d82f41f8f18d7ef1 - -let deployment = - kubernetes.Deployment::{ - , metadata = kubernetes.ObjectMeta::{ name = Some "nginx" } - , spec = Some kubernetes.DeploymentSpec::{ - , replicas = Some +2 - , revisionHistoryLimit = Some +10 - , selector = kubernetes.LabelSelector::{ - , matchLabels = Some (toMap { app = "nginx" }) - } - , strategy = Some kubernetes.DeploymentStrategy::{ - , type = Some "RollingUpdate" - , rollingUpdate = Some - { maxSurge = Some (kubernetes.IntOrString.Int +5) - , maxUnavailable = Some (kubernetes.IntOrString.Int +0) - } - } - , template = kubernetes.PodTemplateSpec::{ - , metadata = Some kubernetes.ObjectMeta::{ - , name = Some "nginx" - , labels = Some (toMap { app = "nginx" }) - } - , spec = Some kubernetes.PodSpec::{ - , containers = - [ kubernetes.Container::{ - , name = "nginx" - , image = Some "nginx:1.15.3" - , imagePullPolicy = Some "Always" - , ports = Some - [ kubernetes.ContainerPort::{ containerPort = +80 } ] - , resources = Some - { limits = Some (toMap { cpu = "500m" }) - , requests = Some (toMap { cpu = "10m" }) - } - } - ] - } - } - } - } - -in deployment diff --git a/1.17/examples/deploymentSimple.dhall b/1.17/examples/deploymentSimple.dhall deleted file mode 100644 index d335c82e..00000000 --- a/1.17/examples/deploymentSimple.dhall +++ /dev/null @@ -1,28 +0,0 @@ -let kubernetes = - ../package.dhall sha256:532e110f424ea8a9f960a13b2ca54779ddcac5d5aa531f86d82f41f8f18d7ef1 - -let deployment = - kubernetes.Deployment::{ - , metadata = kubernetes.ObjectMeta::{ name = Some "nginx" } - , spec = Some kubernetes.DeploymentSpec::{ - , selector = kubernetes.LabelSelector::{ - , matchLabels = Some (toMap { name = "nginx" }) - } - , replicas = Some +2 - , template = kubernetes.PodTemplateSpec::{ - , metadata = Some kubernetes.ObjectMeta::{ name = Some "nginx" } - , spec = Some kubernetes.PodSpec::{ - , containers = - [ kubernetes.Container::{ - , name = "nginx" - , image = Some "nginx:1.15.3" - , ports = Some - [ kubernetes.ContainerPort::{ containerPort = +80 } ] - } - ] - } - } - } - } - -in deployment diff --git a/1.17/examples/ingress.dhall b/1.17/examples/ingress.dhall deleted file mode 100644 index d2852f5e..00000000 --- a/1.17/examples/ingress.dhall +++ /dev/null @@ -1,79 +0,0 @@ -let Prelude = - ../Prelude.dhall sha256:10db3c919c25e9046833df897a8ffe2701dc390fa0893d958c3430524be5a43e - -let map = Prelude.List.map - -let kubernetes = - ../package.dhall sha256:532e110f424ea8a9f960a13b2ca54779ddcac5d5aa531f86d82f41f8f18d7ef1 - -let Service = { name : Text, host : Text, version : Text } - -let services = [ { name = "foo", host = "foo.example.com", version = "2.3" } ] - -let makeTLS - : Service → kubernetes.IngressTLS.Type - = λ(service : Service) → - { hosts = Some [ service.host ] - , secretName = Some "${service.name}-certificate" - } - -let makeRule - : Service → kubernetes.IngressRule.Type - = λ(service : Service) → - { host = Some service.host - , http = Some - { paths = - [ { backend = - { serviceName = service.name - , servicePort = kubernetes.IntOrString.Int +80 - } - , path = None Text - } - ] - } - } - -let mkIngress - : List Service → kubernetes.Ingress.Type - = λ(inputServices : List Service) → - let annotations = - toMap - { `kubernetes.io/ingress.class` = "nginx" - , `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 = Some - ( map - Service - kubernetes.IngressTLS.Type - makeTLS - ingressServices - ) - , rules = Some - ( map - Service - kubernetes.IngressRule.Type - makeRule - ingressServices - ) - } - - in kubernetes.Ingress::{ - , metadata = kubernetes.ObjectMeta::{ - , name = Some "nginx" - , annotations = Some annotations - } - , spec = Some spec - } - -in mkIngress services diff --git a/1.17/examples/out/aws-iam-authenticator-chart.yaml b/1.17/examples/out/aws-iam-authenticator-chart.yaml deleted file mode 100644 index 6492e480..00000000 --- a/1.17/examples/out/aws-iam-authenticator-chart.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: apps/v1 -kind: DaemonSet -metadata: - labels: - app: aws-iam-authenticator - chart: aws-iam-authenticator-0.1.1 - heritage: dhall - release: wintering-rodent - name: wintering-rodent-aws-iam-authenticator -spec: - selector: - matchLabels: - app: aws-iam-authenticator - release: wintering-rodent - template: - metadata: - annotations: - scheduler.alpha.kubernetes.io/critical-pod: '' - labels: - app: aws-iam-authenticator - release: wintering-rodent - name: aws-iam-authenticator - spec: - containers: - - args: - - server - - "--config=/etc/aws-iam-authenticator/config.yaml" - - "--state-dir=/var/aws-iam-authenticator" - - "--generate-kubeconfig=/etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml" - image: gcr.io/heptio-images/authenticator:v0.1.0 - name: wintering-rodent-aws-iam-authenticator - volumeMounts: - - mountPath: /etc/aws-iam-authenticator/ - name: config - - mountPath: /var/aws-iam-authenticator/ - name: state - - mountPath: /etc/kubernetes/aws-iam-authenticator/ - name: output - hostNetwork: true - nodeSelector: - node-role.kubernetes.io/master: '' - tolerations: - - effect: NoSchedule - key: node-role.kubernetes.io/master - - effect: CriticalAddonsOnly - key: Exists - volumes: - - configMap: - name: wintering-rodent-aws-iam-authenticator - name: config - - hostPath: - path: /srv/kubernetes/aws-iam-authenticator/ - name: output - - hostPath: - path: /srv/kubernetes/aws-iam-authenticator/ - name: state - updateStrategy: - type: RollingUpdate diff --git a/1.17/examples/out/deployment.yaml b/1.17/examples/out/deployment.yaml deleted file mode 100644 index 6bc18dc5..00000000 --- a/1.17/examples/out/deployment.yaml +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx -spec: - replicas: 2 - revisionHistoryLimit: 10 - selector: - matchLabels: - app: nginx - strategy: - rollingUpdate: - maxSurge: 5 - maxUnavailable: 0 - type: RollingUpdate - template: - metadata: - labels: - app: nginx - name: nginx - spec: - containers: - - image: nginx:1.15.3 - imagePullPolicy: Always - name: nginx - ports: - - containerPort: 80 - resources: - limits: - cpu: "500m" - requests: - cpu: "10m" diff --git a/1.17/examples/out/deploymentSimple.yaml b/1.17/examples/out/deploymentSimple.yaml deleted file mode 100644 index 79f297ab..00000000 --- a/1.17/examples/out/deploymentSimple.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx -spec: - replicas: 2 - selector: - matchLabels: - name: nginx - template: - metadata: - name: nginx - spec: - containers: - - image: nginx:1.15.3 - name: nginx - ports: - - containerPort: 80 diff --git a/1.17/examples/out/ingress.yaml b/1.17/examples/out/ingress.yaml deleted file mode 100644 index 7580efd5..00000000 --- a/1.17/examples/out/ingress.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: networking.k8s.io/v1beta1 -kind: Ingress -metadata: - annotations: - kubernetes.io/ingress.allow-http: 'false' - 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 diff --git a/1.17/examples/out/service.yaml b/1.17/examples/out/service.yaml deleted file mode 100644 index ca4acc5e..00000000 --- a/1.17/examples/out/service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: nginx - name: nginx -spec: - ports: - - port: 80 - targetPort: 80 - selector: - app: nginx - type: NodePort diff --git a/1.17/examples/service.dhall b/1.17/examples/service.dhall deleted file mode 100644 index 8758cd91..00000000 --- a/1.17/examples/service.dhall +++ /dev/null @@ -1,28 +0,0 @@ -let Prelude = - ../Prelude.dhall sha256:10db3c919c25e9046833df897a8ffe2701dc390fa0893d958c3430524be5a43e - -let kubernetes = - ../package.dhall sha256:532e110f424ea8a9f960a13b2ca54779ddcac5d5aa531f86d82f41f8f18d7ef1 - -let spec = - { selector = Some (toMap { app = "nginx" }) - , type = Some "NodePort" - , ports = Some - [ kubernetes.ServicePort::{ - , targetPort = Some (kubernetes.IntOrString.Int +80) - , port = +80 - } - ] - } - -let service - : kubernetes.Service.Type - = kubernetes.Service::{ - , metadata = kubernetes.ObjectMeta::{ - , name = Some "nginx" - , labels = Some (toMap { app = "nginx" }) - } - , spec = Some kubernetes.ServiceSpec::spec - } - -in service diff --git a/README.md b/README.md index e65dd619..869d6aa9 100644 --- a/README.md +++ b/README.md @@ -298,14 +298,64 @@ in } ``` - ## Projects Using `dhall-kubernetes` * [dhall-prometheus-operator][dhall-prometheus-operator]: Provides types and default records for [Prometheus Operators][prometheus-operator]. - ## Development +You will need to install Nix in order to run the file-generation scripts +provided by this repository. You can obtain Nix by following the instructions +here: + +* [`nixos.org` - Getting Nix](https://nixos.org/download.html) + +### Updating the `README.md` + +The top-level `README.md` is generated from `./docs/README.md.dhall` so that +the examples within the `./examples` directory stay in sync with the +`README.md`. That means that in order to update the `README.md` you need to +first edit `./docs/README.md.dhall` and then run: + +```bash +$ ./scripts/generate readme +``` + +### Updating the examples + +If you want to author new examples, add them to the `./examples` directory and +run: + +```bash +$ ./scripts/generate examples +``` + +… which will freeze and type-check each example and generate the matching YAML +output. + +The `./examples` directory is only built against one version of the Kubernetes +API (the "preferred" version). To change the preferred version, run: + +```bash +$ echo "${VERSION}" > ./nix/preferred.txt +``` + +… and then re-run the example generation script: + +```bash +$ ./scripts/generate examples +``` + +### Adding a new Kubernetes releases + +To add a new supported Kubernetes release, run: + +```bash +./scripts/add-kubernetes-release "${VERSION}" +``` + +### Changing how the Kubernetes bindings are generated + The logic for generating the Dhall code doesn't reside within this repository but actually resides within the [`dhall-openapi`](https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-openapi) @@ -324,27 +374,26 @@ then CI will reject the pull request since it verifies that the Dhall code stored in version control matches what `dhall-openapi` would generate from the Kubernetes OpenAPI specification. +Once you update the `dhall-openapi` dependency you can regenerate the +Kubernetes bindings by running: + +```bash +$ ./scripts/generate kubernetes +``` + ### Updating the `dhall-openapi` dependency The `dhall-openapi` dependency is a subproject of the `dhall-haskell` repository, so in order to upgrade `dhall-openapi` you need to update the reference to the `dhall-haskell` repository. -To upgrade to the latest version of the `dhall-openapi` package, run: - -```bash -nix-prefetch-git --fetch-submodules https://github.com/dhall-lang/dhall-haskell.git > ./nix/dhall-haskell.json -``` - -If you want to build against a local copy of `dhall-haskell`, then edit the -Nix code like this: +If you're not prepared to make a pull request to change the `dhall-haskell` +project then you can generate code for this project using a local checkout of +the `dhall-haskell` repository by editing the Nix code like this: ```diff -diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix -index 832ae1a..810e966 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix -@@ -126,11 +126,7 @@ let json = builtins.fromJSON (builtins.readFile ./dhall-haskell.json); @@ -359,21 +408,28 @@ index 832ae1a..810e966 100644 (import "${dhall-haskell}/default.nix").dhall-openapi; ``` -### Adding a new Kubernetes releases - -To add a new supported release, run: +Once you do change the upstream `dhall-openapi` project, then you can pick up +the change here by runing: ```bash -./scripts/add-kubernetes-release.sh "${VERSION}" +$ nix-prefetch-git --fetch-submodules https://github.com/dhall-lang/dhall-haskell.git > ./nix/dhall-haskell.json ``` -… and then create a pull request out of the generated files. +### Generating everything -If you want to make a specific release the preferred release, run: +If you're not sure what files you need to regenerate then you can generate +everything by running the `generate` script with no arguments: +```bash +$ ./scripts/generate ``` -$ echo "${VERSION}" > ./nix/preferred.txt -$ ./scripts/generate.sh + +### Upgrading Nixpkgs + +If you want to upgrade to a newer revision of Nixpkgs, then run: + +```bash +$ nix-prefetch-git https://github.com/NixOS/nixpkgs.git "${REVISION}" > ./nix/nixpkgs.json ``` ### Tests @@ -387,16 +443,6 @@ You can run the tests locally with the following command: 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 `docs/README.md.dhall`, you need to run this command -afterwards. - - [stack]: https://haskellstack.org/ [hydra-project]: http://hydra.dhall-lang.org/project/dhall-kubernetes [dhall-lang]: https://github.com/dhall-lang/dhall-lang diff --git a/docs/README.md.dhall b/docs/README.md.dhall index f7fb9641..88d078ce 100644 --- a/docs/README.md.dhall +++ b/docs/README.md.dhall @@ -146,14 +146,64 @@ in } ``` - ## Projects Using `dhall-kubernetes` * [dhall-prometheus-operator][dhall-prometheus-operator]: Provides types and default records for [Prometheus Operators][prometheus-operator]. - ## Development +You will need to install Nix in order to run the file-generation scripts +provided by this repository. You can obtain Nix by following the instructions +here: + +* [`nixos.org` - Getting Nix](https://nixos.org/download.html) + +### Updating the `README.md` + +The top-level `README.md` is generated from `./docs/README.md.dhall` so that +the examples within the `./examples` directory stay in sync with the +`README.md`. That means that in order to update the `README.md` you need to +first edit `./docs/README.md.dhall` and then run: + +```bash +$ ./scripts/generate readme +``` + +### Updating the examples + +If you want to author new examples, add them to the `./examples` directory and +run: + +```bash +$ ./scripts/generate examples +``` + +… which will freeze and type-check each example and generate the matching YAML +output. + +The `./examples` directory is only built against one version of the Kubernetes +API (the "preferred" version). To change the preferred version, run: + +```bash +$ echo "''${VERSION}" > ./nix/preferred.txt +``` + +… and then re-run the example generation script: + +```bash +$ ./scripts/generate examples +``` + +### Adding a new Kubernetes releases + +To add a new supported Kubernetes release, run: + +```bash +./scripts/add-kubernetes-release "''${VERSION}" +``` + +### Changing how the Kubernetes bindings are generated + The logic for generating the Dhall code doesn't reside within this repository but actually resides within the [`dhall-openapi`](https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-openapi) @@ -172,27 +222,26 @@ then CI will reject the pull request since it verifies that the Dhall code stored in version control matches what `dhall-openapi` would generate from the Kubernetes OpenAPI specification. +Once you update the `dhall-openapi` dependency you can regenerate the +Kubernetes bindings by running: + +```bash +$ ./scripts/generate kubernetes +``` + ### Updating the `dhall-openapi` dependency The `dhall-openapi` dependency is a subproject of the `dhall-haskell` repository, so in order to upgrade `dhall-openapi` you need to update the reference to the `dhall-haskell` repository. -To upgrade to the latest version of the `dhall-openapi` package, run: - -```bash -nix-prefetch-git --fetch-submodules https://github.com/dhall-lang/dhall-haskell.git > ./nix/dhall-haskell.json -``` - -If you want to build against a local copy of `dhall-haskell`, then edit the -Nix code like this: +If you're not prepared to make a pull request to change the `dhall-haskell` +project then you can generate code for this project using a local checkout of +the `dhall-haskell` repository by editing the Nix code like this: ```diff -diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix -index 832ae1a..810e966 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix -@@ -126,11 +126,7 @@ let json = builtins.fromJSON (builtins.readFile ./dhall-haskell.json); @@ -207,21 +256,28 @@ index 832ae1a..810e966 100644 (import "''${dhall-haskell}/default.nix").dhall-openapi; ``` -### Adding a new Kubernetes releases - -To add a new supported release, run: +Once you do change the upstream `dhall-openapi` project, then you can pick up +the change here by runing: ```bash -./scripts/add-kubernetes-release.sh "''${VERSION}" +$ nix-prefetch-git --fetch-submodules https://github.com/dhall-lang/dhall-haskell.git > ./nix/dhall-haskell.json ``` -… and then create a pull request out of the generated files. +### Generating everything -If you want to make a specific release the preferred release, run: +If you're not sure what files you need to regenerate then you can generate +everything by running the `generate` script with no arguments: +```bash +$ ./scripts/generate ``` -$ echo "''${VERSION}" > ./nix/preferred.txt -$ ./scripts/generate.sh + +### Upgrading Nixpkgs + +If you want to upgrade to a newer revision of Nixpkgs, then run: + +```bash +$ nix-prefetch-git https://github.com/NixOS/nixpkgs.git "''${REVISION}" > ./nix/nixpkgs.json ``` ### Tests @@ -235,16 +291,6 @@ You can run the tests locally with the following command: 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 `docs/README.md.dhall`, you need to run this command -afterwards. - - [stack]: https://haskellstack.org/ [hydra-project]: http://hydra.dhall-lang.org/project/dhall-kubernetes [dhall-lang]: https://github.com/dhall-lang/dhall-lang diff --git a/nix/dhall-kubernetes.nix b/nix/dhall-kubernetes.nix index 33f560ef..4f6af707 100644 --- a/nix/dhall-kubernetes.nix +++ b/nix/dhall-kubernetes.nix @@ -1,4 +1,4 @@ -{ fetchurl, make-dhall-kubernetes-package, lib, stdenv }: +{ fetchurl, make-dhall-kubernetes, lib, stdenv }: let kubernetesDirectory = ./kubernetes; @@ -35,7 +35,7 @@ let ''; }; in - make-dhall-kubernetes-package { inherit version spec; }; + make-dhall-kubernetes spec; }; in diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json index b7fc764b..45e8bd5c 100644 --- a/nix/nixpkgs.json +++ b/nix/nixpkgs.json @@ -1,9 +1,7 @@ { "url": "https://github.com/NixOS/nixpkgs.git", - "rev": "2cd2e7267e5b9a960c2997756cb30e86f0958a6b", - "date": "2020-06-23T09:46:29+03:00", - "sha256": "0ir3rk776wldyjz6l6y5c5fs8lqk95gsik6w45wxgk6zdpsvhrn5", - "fetchSubmodules": false, - "deepClone": false, - "leaveDotGit": false + "rev": "ae66c3e40486c0e88a6cefc8d275c248fc6a696c", + "date": "2021-02-19T13:13:16+10:00", + "sha256": "1gw4kdlkmxyil8capnagv41hqmh31hkibidjgy3bxhlljr8xgfkc", + "fetchSubmodules": false } diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 77defb99..af8a6fd4 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -6,119 +6,101 @@ let }; overlay = pkgsNew: pkgsOld: { - make-dhall-kubernetes = - spec: - pkgsNew.runCommand "dhall-${spec.name}" {} '' - ${pkgsNew.coreutils}/bin/mkdir -p $out + make-dhall-kubernetes = spec: + let + frozenFiles = [ + "defaults.dhall" + "types.dhall" + "schemas.dhall" + "typesUnion.dhall" + "package.dhall" + ]; - cd $out - - ${pkgsNew.haskellPackages.dhall-openapi}/bin/openapi-to-dhall '${spec}' + freeze = file: '' + echo 'Freezing ./${file}' + ${pkgsNew.coreutils}/bin/chmod u+w "$out/${file}" + ${pkgsNew.dhall}/bin/dhall freeze --all --inplace "$out/${file}" + echo 'Checking ./${file}' + ${pkgsNew.dhall}/bin/dhall type --quiet --file "$out/${file}" ''; - make-dhall-kubernetes-package = - { version, spec }: - let - preferredVersion = + in + pkgsNew.runCommand "dhall-${spec.name}" { XDG_CACHE_HOME=".cache"; } '' + ${pkgsNew.coreutils}/bin/mkdir "$out" + cd $out + ${pkgsNew.haskellPackages.dhall-openapi}/bin/openapi-to-dhall '${spec}' + ${pkgsNew.lib.concatMapStringsSep "\n" freeze frozenFiles} + ${pkgsNew.coreutils}/bin/rm --recursive .cache + ''; + + examples = + let + preferredVersion = + let + preferredVersionText = builtins.readFile ./preferred.txt; + + in + builtins.replaceStrings [ "\n" ] [ "" ] preferredVersionText; + + examplePaths = + pkgsNew.lib.filterAttrs (name: _: name != "out") + (builtins.readDir ../examples); + + exampleNames = + pkgsNew.lib.mapAttrsToList + (name: _: builtins.replaceStrings [ ".dhall" ] [ "" ] name) + examplePaths; + + copyExample = + example: "${pkgsNew.coreutils}/bin/cp ${./../examples + "/${example}.dhall"} ./examples/${example}.dhall"; + + freeze = example: + let + file = "./examples/${example}.dhall"; + + in + '' + echo 'Freezing ${file}' + ${pkgsNew.coreutils}/bin/chmod u+w ${file} + ${pkgsNew.dhall}/bin/dhall freeze --all --inplace ${file} + echo 'Checking ${file}' + ${pkgsNew.dhall}/bin/dhall type --quiet --file ${file} + ''; + + + buildExample = + example: let - preferredVersionText = builtins.readFile ./preferred.txt; + inputFile = "./examples/${example}.dhall"; + + outputFile = "./examples/out/${example}.yaml"; in - builtins.replaceStrings [ "\n" ] [ "" ] preferredVersionText; - - drv = pkgsNew.make-dhall-kubernetes spec; - - kubernetesFiles = [ - "defaults.dhall" - "types.dhall" - "schemas.dhall" - "typesUnion.dhall" - "package.dhall" - ]; - - examples = pkgsNew.lib.optionals (version == preferredVersion) [ - "aws-iam-authenticator-chart" - "deployment" - "deploymentSimple" - "ingress" - "service" - ]; - - exampleFiles = - let - exampleToLocal = example: "examples/${example}.dhall"; - - in - map exampleToLocal examples; - - otherFiles = pkgsNew.lib.optionals (version == preferredVersion) [ - "Prelude.dhall" - "docs/README.md.dhall" - ]; - - copiedFiles = exampleFiles ++ otherFiles; - - frozenFiles = kubernetesFiles ++ exampleFiles; - - checkedFiles = frozenFiles; - - copyKubernetes = - file: - "${pkgsNew.coreutils}/bin/cp ${drv}/${file} $out/${file}"; - - copyLocal = - file: - "${pkgsNew.coreutils}/bin/cp ${./.. + "/${file}"} $out/${file}"; - - freezeFile = - file: - ''echo 'Freezing ./${file}' - ${pkgsNew.dhall}/bin/dhall freeze --all --inplace $out/${file} - echo 'Checking ./${file}' - ${pkgsNew.dhall}/bin/dhall type --quiet --file $out/${file} + '' + echo '${inputFile} → ${outputFile}' + ${pkgsNew.dhall-json}/bin/dhall-to-yaml --file ${inputFile} > ${outputFile} ''; - buildExample = - example: - let - inputFile = "examples/${example}.dhall"; + in + pkgsNew.runCommand "examples" { XDG_CACHE_HOME=".cache"; } '' + ${pkgsNew.coreutils}/bin/mkdir --parents ./examples/out + ${pkgsNew.lib.concatMapStringsSep "\n" copyExample exampleNames} + ${pkgsNew.coreutils}/bin/cp ${../Prelude.dhall} ./Prelude.dhall + ${pkgsNew.rsync}/bin/rsync --recursive ${pkgsNew.dhall-kubernetes."${preferredVersion}"}/ ./ + ${pkgsNew.lib.concatMapStringsSep "\n" freeze exampleNames} + ${pkgsNew.lib.concatMapStringsSep "\n" buildExample exampleNames} + ${pkgsNew.coreutils}/bin/mkdir "$out" + ${pkgsNew.rsync}/bin/rsync --recursive ./examples/ $out/ + ''; - outputFile = "examples/out/${example}.yaml"; + readme = + pkgsNew.runCommand "README.md" {} '' + ${pkgsNew.coreutils}/bin/mkdir ./docs + ${pkgsNew.coreutils}/bin/ln --symbolic ${pkgsNew.examples} ./examples + ${pkgsNew.coreutils}/bin/ln --symbolic ${../docs/README.md.dhall} ./docs/README.md.dhall - in - ''echo './${inputFile} → ./${outputFile}' - ${pkgsNew.dhall-json}/bin/dhall-to-yaml --file $out/${inputFile} > $out/${outputFile} - ''; - - in - pkgsNew.runCommand "package-${drv.name}" { XDG_CACHE_HOME="."; } '' - ${pkgsNew.coreutils}/bin/mkdir --parents "$out/examples/out" - ${pkgsNew.coreutils}/bin/mkdir --parents "$out/docs" - ${pkgsNew.rsync}/bin/rsync --recursive ${drv}/ $out/ - ${pkgsNew.coreutils}/bin/chmod u+w $out/ - ${pkgsNew.lib.concatMapStringsSep "\n" copyLocal copiedFiles} - ${pkgsNew.coreutils}/bin/chmod u+w --recursive $out/ - ${pkgsNew.lib.concatMapStringsSep "\n" freezeFile frozenFiles} - ${pkgsNew.lib.concatMapStringsSep "\n" buildExample examples} - ${let - inputFile = "docs/README.md.dhall"; - - outputFile = "README.md"; - - in - if (version == preferredVersion) - then - ''echo './${inputFile} → ./${outputFile}' - - ${pkgsNew.dhall}/bin/dhall text --file $out/${inputFile} | ${pkgsNew.gnused}/bin/sed 's_\.\./package.dhall_https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/master/package.dhall_g' > $out/${outputFile} - '' - else - '' - ${pkgsNew.coreutils}/bin/rm --recursive $out/examples - '' - } - ${pkgsNew.coreutils}/bin/rm --recursive $out/docs - ''; + ${pkgsNew.dhall}/bin/dhall text --file "./docs/README.md.dhall" | ${pkgsNew.gnused}/bin/sed 's_\.\./package.dhall_https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/master/package.dhall_g' > "$out" + ''; dhall-kubernetes = pkgsNew.callPackage ./dhall-kubernetes.nix {}; diff --git a/release.nix b/release.nix index fb5ba207..c6b3eb31 100644 --- a/release.nix +++ b/release.nix @@ -11,6 +11,8 @@ let # commit doesn't make any changes (which can happen when merging # master in). rev = pkgs.runCommand "rev" {} ''echo "${src.rev}" > $out''; + + inherit (pkgs) examples readme; } // builtins.removeAttrs pkgs.dhall-kubernetes [ "override" "overrideDerivation" ] // builtins.removeAttrs pkgs.dhall-kubernetes-tests diff --git a/scripts/add-kubernetes-release.sh b/scripts/add-kubernetes-release similarity index 82% rename from scripts/add-kubernetes-release.sh rename to scripts/add-kubernetes-release index 6e9d64bb..e937f6a3 100755 --- a/scripts/add-kubernetes-release.sh +++ b/scripts/add-kubernetes-release @@ -5,4 +5,4 @@ set -eu VERSION="$1" nix-prefetch-url "https://github.com/kubernetes/kubernetes/archive/release-${VERSION}.tar.gz" > "nix/kubernetes/${VERSION}.txt" -./scripts/generate.sh "${VERSION}" +./scripts/generate preferred diff --git a/scripts/generate b/scripts/generate new file mode 100755 index 00000000..8e8227f3 --- /dev/null +++ b/scripts/generate @@ -0,0 +1,71 @@ +#!/bin/sh + +set -e + +kubernetes_version () { + VERSION="${1}" + + DIR="$(nix-build release.nix --attr "\"${VERSION}\"" --no-out-link)" + + rm -r "${VERSION}" + mkdir -p "${VERSION}" + + for FILE in defaults types schemas types.dhall typesUnion.dhall defaults.dhall schemas.dhall package.dhall; do + cp -r "${DIR}/${FILE}" "${VERSION}" + + chmod -R u+w "${VERSION}/${FILE}" + done +} + +kubernetes () { + for KUBERNETES_FILE in ./nix/kubernetes/*.txt; do + KUBERNETES_FILE_WITHOUT_EXTENSION="${KUBERNETES_FILE%.txt}" + + VERSION="${KUBERNETES_FILE_WITHOUT_EXTENSION#./nix/kubernetes/}" + + kubernetes_version "${VERSION}" + done +} + +examples () { + DIR="$(nix-build release.nix --attr examples)" + + rm -r ./examples + + cp -r "${DIR}/" ./examples + chmod -R u+w ./examples +} + +readme () { + FILE="$(nix-build release.nix --attr readme)" + + cp "${FILE}" README.md + chmod u+w README.md +} + +preferred () { + PREFERRED_VERSION="$(cat ./nix/preferred.txt)" + + kubernetes_version "${PREFERRED_VERSION}" + + for FILE in {package,types,defaults,schemas,typesUnion}.dhall; do + echo "./${PREFERRED_VERSION}/${FILE}" > "${FILE}" + done + + examples + + readme +} + +if [ -n "$1" ]; then + case "$1" in + kubernetes) kubernetes;; + examples) examples;; + readme) readme;; + esac +else + kubernetes + examples + readme + preferred +fi diff --git a/scripts/generate.sh b/scripts/generate.sh deleted file mode 100755 index 95c385de..00000000 --- a/scripts/generate.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -PREFERRED_VERSION="$(cat ./nix/preferred.txt)" - -if [ -n "$1" ]; then - VERSION="$1" - BASE="$1" -else - VERSION="${PREFERRED_VERSION}" - BASE="." -fi - -mkdir -p "${BASE}" - -if DIR=$(nix-build release.nix --attr "\"${VERSION}\"" --no-out-link); then - rm -rf "${BASE}" - mkdir -p "${BASE}" - cp -r "${DIR}/defaults" "${BASE}" - chmod -R u+w "${BASE}/defaults" - cp -r "${DIR}/types" "${BASE}" - chmod -R u+w "${BASE}/types" - cp -r "${DIR}/schemas" "${BASE}" - chmod -R u+w "${BASE}/schemas" - cp "${DIR}/types.dhall" "${DIR}/typesUnion.dhall" "${DIR}/defaults.dhall" "${DIR}/schemas.dhall" "${DIR}/package.dhall" "${BASE}" - chmod u+w "${BASE}/types.dhall" "${BASE}/typesUnion.dhall" "${BASE}/defaults.dhall" "${BASE}/schemas.dhall" "${BASE}/package.dhall" - if [ "${VERSION}" = "${PREFERRED_VERSION}" ]; then - cp -r "${DIR}/examples" "${BASE}" - chmod -R u+w "${BASE}/examples" - cp "${DIR}/Prelude.dhall" "${DIR}/README.md" "${BASE}" - chmod u+w "${BASE}/Prelude.dhall" "${BASE}/README.md" - fi -fi