Update to dhall lang v17

This change updates the dhall code to the latest version.

* Support for record pun where `{ x = x }` can now be written as `{ x }`
* Indentation and function definitions are more compact

This change has been generated after installing dhall v1.33 using this
command: find . -name "*.dhall" -exec dhall --ascii format --inplace {} \;

Change-Id: I3b6560f26e28622aa51150dc8083d127d89a8a7b
changes/67/739767/3
Tristan Cacqueray 2 years ago
parent 0fbffe66f2
commit 06b4062e4b
  1. 8
      build/Dockerfile
  2. 19
      conf/CertManager.dhall
  3. 4
      conf/Prelude.dhall
  4. 72
      conf/zuul/components/Database.dhall
  5. 108
      conf/zuul/components/Executor.dhall
  6. 46
      conf/zuul/components/Merger.dhall
  7. 62
      conf/zuul/components/Preview.dhall
  8. 110
      conf/zuul/components/Registry.dhall
  9. 62
      conf/zuul/components/Scheduler.dhall
  10. 60
      conf/zuul/components/Web.dhall
  11. 72
      conf/zuul/components/ZooKeeper.dhall
  12. 12
      conf/zuul/files/nodepool.yaml.dhall
  13. 34
      conf/zuul/files/registry.yaml.dhall
  14. 40
      conf/zuul/files/zoo.cfg.dhall
  15. 364
      conf/zuul/files/zuul.conf.dhall
  16. 357
      conf/zuul/functions.dhall
  17. 183
      conf/zuul/input.dhall
  18. 983
      conf/zuul/resources.dhall

@ -1,10 +1,10 @@
FROM quay.io/operator-framework/ansible-operator:v0.13.0
# dhall versions and digests
ARG DHALL_VERSION=1.30.0
ARG DHALL_JSON_VERSION=1.6.2
ARG DHALL_JSON_DIGEST=ea37627c4e19789af33def099d4cb145b874c03b4d5b98cb33ce06be1debf4f3
ARG DHALL_LANG_REF=v14.0.0
ARG DHALL_VERSION=1.33.1
ARG DHALL_JSON_VERSION=1.7.0
ARG DHALL_JSON_DIGEST=cc9fc70e492d35a3986183b589a435653e782f67cda51d33a935dff1ddd15aec
ARG DHALL_LANG_REF=v17.0.0
ARG DHALL_KUBE_REF=v4.0.0
# kubectl versions and digests

@ -32,11 +32,11 @@ let CertificateSpec =
, issuerRef : { name : Text, kind : Text, group : Text }
}
, default =
{ isCA = None Bool
, usages = None (List Text)
, commonName = None Text
, dnsNames = None (List Text)
}
{ isCA = None Bool
, usages = None (List Text)
, commonName = None Text
, dnsNames = None (List Text)
}
}
let Certificate =
@ -47,7 +47,7 @@ let Certificate =
, spec : CertificateSpec.Type
}
, default =
{ apiVersion = "cert-manager.io/v1alpha3", kind = "Certificate" }
{ apiVersion = "cert-manager.io/v1alpha3", kind = "Certificate" }
}
let Union =
@ -56,9 +56,4 @@ let Union =
| Certificate : Certificate.Type
>
in { IssuerSpec = IssuerSpec
, Issuer = Issuer
, CertificateSpec = CertificateSpec
, Certificate = Certificate
, Union = Union
}
in { IssuerSpec, Issuer, CertificateSpec, Certificate, Union }

@ -24,5 +24,5 @@
* https://github.com/dhall-lang/dhall-nethack/blob/master/Prelude.dhall
-}
env:DHALL_PRELUDE
? https://prelude.dhall-lang.org/v13.0.0/package.dhall sha256:4aa8581954f7734d09b7b21fddbf5d8df901a44b54b4ef26ea71db92de0b1a12
? https://prelude.dhall-lang.org/v13.0.0/package.dhall
? https://prelude.dhall-lang.org/v17.0.0/package.dhall sha256:10db3c919c25e9046833df897a8ffe2701dc390fa0893d958c3430524be5a43e
? https://prelude.dhall-lang.org/v17.0.0/package.dhall

@ -4,41 +4,41 @@ let F = ../functions.dhall
let db-volumes = [ F.Volume::{ name = "pg-data", dir = "/var/lib/pg/" } ]
in \(app-name : Text)
-> \ ( db-internal-password-env
: forall (env-name : Text) -> List Kubernetes.EnvVar.Type
)
-> F.KubernetesComponent::{
, Service = Some (F.mkService app-name "db" "pg" 5432)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
in \(app-name : Text) ->
\ ( db-internal-password-env
: forall (env-name : Text) -> List Kubernetes.EnvVar.Type
) ->
F.KubernetesComponent::{
, Service = Some (F.mkService app-name "db" "pg" 5432)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
, name = "db"
, count = 1
, data-dir = db-volumes
, claim-size = 1
, container = Kubernetes.Container::{
, name = "db"
, count = 1
, data-dir = db-volumes
, claim-size = 1
, container = Kubernetes.Container::{
, name = "db"
, image = Some "docker.io/library/postgres:12.1"
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "pg"
, containerPort = 5432
}
]
, env = Some
( F.mkEnvVarValue
( toMap
{ POSTGRES_USER = "zuul"
, PGDATA = "/var/lib/pg/data"
}
)
# db-internal-password-env "POSTGRES_PASSWORD"
)
, volumeMounts = Some (F.mkVolumeMount db-volumes)
}
, image = Some "docker.io/library/postgres:12.1"
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "pg"
, containerPort = 5432
}
]
, env = Some
( F.mkEnvVarValue
( toMap
{ POSTGRES_USER = "zuul"
, PGDATA = "/var/lib/pg/data"
}
)
# db-internal-password-env "POSTGRES_PASSWORD"
)
, volumeMounts = Some (F.mkVolumeMount db-volumes)
}
)
}
}
)
}

@ -6,63 +6,63 @@ let InputExecutor = (../input.dhall).Executor.Type
let JobVolume = (../input.dhall).JobVolume.Type
in \(app-name : Text)
-> \(input-executor : InputExecutor)
-> \(data-dir : List F.Volume.Type)
-> \(volumes : List F.Volume.Type)
-> \(env : List Kubernetes.EnvVar.Type)
-> \(jobVolumes : Optional (List JobVolume))
-> F.KubernetesComponent::{
, Service = Some (F.mkService app-name "executor" "finger" 7900)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
in \(app-name : Text) ->
\(input-executor : InputExecutor) ->
\(data-dir : List F.Volume.Type) ->
\(volumes : List F.Volume.Type) ->
\(env : List Kubernetes.EnvVar.Type) ->
\(jobVolumes : Optional (List JobVolume)) ->
F.KubernetesComponent::{
, Service = Some (F.mkService app-name "executor" "finger" 7900)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
, name = "executor"
, count = 1
, data-dir
, volumes
, extra-volumes =
let job-volumes =
F.mkJobVolume
Kubernetes.Volume.Type
(\(job-volume : JobVolume) -> job-volume.volume)
jobVolumes
in job-volumes
, claim-size = 0
, container = Kubernetes.Container::{
, name = "executor"
, count = 1
, data-dir = data-dir
, volumes = volumes
, extra-volumes =
let job-volumes =
, image = input-executor.image
, args = Some [ "zuul-executor", "-d" ]
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "finger"
, containerPort = 7900
}
]
, env = Some env
, volumeMounts =
let job-volumes-mount =
F.mkJobVolume
Kubernetes.Volume.Type
(\(job-volume : JobVolume) -> job-volume.volume)
F.Volume.Type
( \(job-volume : JobVolume) ->
F.Volume::{
, name = job-volume.volume.name
, dir = job-volume.dir
}
)
jobVolumes
in job-volumes
, claim-size = 0
, container = Kubernetes.Container::{
, name = "executor"
, image = input-executor.image
, args = Some [ "zuul-executor", "-d" ]
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "finger"
, containerPort = 7900
}
]
, env = Some env
, volumeMounts =
let job-volumes-mount =
F.mkJobVolume
F.Volume.Type
( \(job-volume : JobVolume)
-> F.Volume::{
, name = job-volume.volume.name
, dir = job-volume.dir
}
)
jobVolumes
in Some
( F.mkVolumeMount
(data-dir # volumes # job-volumes-mount)
)
, securityContext = Some Kubernetes.SecurityContext::{
, privileged = Some True
}
in Some
( F.mkVolumeMount
(data-dir # volumes # job-volumes-mount)
)
, securityContext = Some Kubernetes.SecurityContext::{
, privileged = Some True
}
}
)
}
}
)
}

@ -4,28 +4,28 @@ let F = ../functions.dhall
let InputMerger = (../input.dhall).Merger.Type
in \(app-name : Text)
-> \(input-merger : InputMerger)
-> \(data-dir : List F.Volume.Type)
-> \(volumes : List F.Volume.Type)
-> \(env : List Kubernetes.EnvVar.Type)
-> F.KubernetesComponent::{
, Deployment = Some
( F.mkDeployment
app-name
F.Component::{
in \(app-name : Text) ->
\(input-merger : InputMerger) ->
\(data-dir : List F.Volume.Type) ->
\(volumes : List F.Volume.Type) ->
\(env : List Kubernetes.EnvVar.Type) ->
F.KubernetesComponent::{
, Deployment = Some
( F.mkDeployment
app-name
F.Component::{
, name = "merger"
, count = 1
, data-dir
, volumes
, container = Kubernetes.Container::{
, name = "merger"
, count = 1
, data-dir = data-dir
, volumes = volumes
, container = Kubernetes.Container::{
, name = "merger"
, image = input-merger.image
, args = Some [ "zuul-merger", "-d" ]
, imagePullPolicy = Some "IfNotPresent"
, env = Some env
, volumeMounts = Some (F.mkVolumeMount (data-dir # volumes))
}
, image = input-merger.image
, args = Some [ "zuul-merger", "-d" ]
, imagePullPolicy = Some "IfNotPresent"
, env = Some env
, volumeMounts = Some (F.mkVolumeMount (data-dir # volumes))
}
)
}
}
)
}

@ -4,36 +4,36 @@ let F = ../functions.dhall
let InputPreview = (../input.dhall).Preview.Type
in \(app-name : Text)
-> \(input-preview : InputPreview)
-> \(data-dir : List F.Volume.Type)
-> F.KubernetesComponent::{
, Service = Some (F.mkService app-name "preview" "preview" 80)
, Deployment = Some
( F.mkDeployment
app-name
F.Component::{
in \(app-name : Text) ->
\(input-preview : InputPreview) ->
\(data-dir : List F.Volume.Type) ->
F.KubernetesComponent::{
, Service = Some (F.mkService app-name "preview" "preview" 80)
, Deployment = Some
( F.mkDeployment
app-name
F.Component::{
, name = "preview"
, count = F.defaultNat input-preview.count 0
, data-dir
, container = Kubernetes.Container::{
, name = "preview"
, count = F.defaultNat input-preview.count 0
, data-dir = data-dir
, container = Kubernetes.Container::{
, name = "preview"
, image = input-preview.image
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "preview"
, containerPort = 80
}
]
, env = Some
[ Kubernetes.EnvVar::{
, name = "ZUUL_API_URL"
, value = Some "http://web:9000"
}
]
, volumeMounts = Some (F.mkVolumeMount data-dir)
}
, image = input-preview.image
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "preview"
, containerPort = 80
}
]
, env = Some
[ Kubernetes.EnvVar::{
, name = "ZUUL_API_URL"
, value = Some "http://web:9000"
}
]
, volumeMounts = Some (F.mkVolumeMount data-dir)
}
)
}
}
)
}

@ -7,65 +7,61 @@ let F = ../functions.dhall
let InputRegistry = (../input.dhall).Registry.Type
let registry-volumes =
\(app-name : Text)
-> [ F.Volume::{
, name = app-name ++ "-registry-tls"
, dir = "/etc/zuul-registry"
}
]
\(app-name : Text) ->
[ F.Volume::{
, name = app-name ++ "-registry-tls"
, dir = "/etc/zuul-registry"
}
]
let registry-env =
\(app-name : Text)
-> F.mkEnvVarSecret
( Prelude.List.map
Text
F.EnvSecret
( \(key : Text)
-> { name = "ZUUL_REGISTRY_${key}"
, key = key
, secret = "${app-name}-registry-user-rw"
}
)
[ "secret", "username", "password" ]
)
\(app-name : Text) ->
F.mkEnvVarSecret
( Prelude.List.map
Text
F.EnvSecret
( \(key : Text) ->
{ name = "ZUUL_REGISTRY_${key}"
, key
, secret = "${app-name}-registry-user-rw"
}
)
[ "secret", "username", "password" ]
)
in \(app-name : Text)
-> \(input-registry : InputRegistry)
-> \(data-dir : List F.Volume.Type)
-> \(volumes : List F.Volume.Type)
-> F.KubernetesComponent::{
, Service = Some (F.mkService app-name "registry" "registry" 9000)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
in \(app-name : Text) ->
\(input-registry : InputRegistry) ->
\(data-dir : List F.Volume.Type) ->
\(volumes : List F.Volume.Type) ->
F.KubernetesComponent::{
, Service = Some (F.mkService app-name "registry" "registry" 9000)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
, name = "registry"
, count = F.defaultNat input-registry.count 0
, data-dir
, volumes = volumes # registry-volumes app-name
, claim-size = F.defaultNat input-registry.storage-size 20
, container = Kubernetes.Container::{
, name = "registry"
, count = F.defaultNat input-registry.count 0
, data-dir = data-dir
, volumes = volumes # registry-volumes app-name
, claim-size = F.defaultNat input-registry.storage-size 20
, container = Kubernetes.Container::{
, name = "registry"
, image = input-registry.image
, args = Some
[ "zuul-registry"
, "-c"
, "/etc/zuul/registry.yaml"
, "serve"
]
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "registry"
, containerPort = 9000
}
]
, env = Some (registry-env app-name)
, volumeMounts = Some
( F.mkVolumeMount
(data-dir # volumes # registry-volumes app-name)
)
}
, image = input-registry.image
, args = Some
[ "zuul-registry", "-c", "/etc/zuul/registry.yaml", "serve" ]
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "registry"
, containerPort = 9000
}
]
, env = Some (registry-env app-name)
, volumeMounts = Some
( F.mkVolumeMount
(data-dir # volumes # registry-volumes app-name)
)
}
)
}
}
)
}

@ -4,36 +4,36 @@ let F = ../functions.dhall
let InputScheduler = (../input.dhall).Scheduler.Type
in \(app-name : Text)
-> \(input-scheduler : InputScheduler)
-> \(data-dir : List F.Volume.Type)
-> \(volumes : List F.Volume.Type)
-> \(env : List Kubernetes.EnvVar.Type)
-> F.KubernetesComponent::{
, Service = Some (F.mkService app-name "scheduler" "gearman" 4730)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
in \(app-name : Text) ->
\(input-scheduler : InputScheduler) ->
\(data-dir : List F.Volume.Type) ->
\(volumes : List F.Volume.Type) ->
\(env : List Kubernetes.EnvVar.Type) ->
F.KubernetesComponent::{
, Service = Some (F.mkService app-name "scheduler" "gearman" 4730)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
, name = "scheduler"
, count = 1
, data-dir
, volumes
, claim-size = 5
, container = Kubernetes.Container::{
, name = "scheduler"
, count = 1
, data-dir = data-dir
, volumes = volumes
, claim-size = 5
, container = Kubernetes.Container::{
, name = "scheduler"
, image = input-scheduler.image
, args = Some [ "zuul-scheduler", "-d" ]
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "gearman"
, containerPort = 4730
}
]
, env = Some env
, volumeMounts = Some (F.mkVolumeMount (data-dir # volumes))
}
, image = input-scheduler.image
, args = Some [ "zuul-scheduler", "-d" ]
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "gearman"
, containerPort = 4730
}
]
, env = Some env
, volumeMounts = Some (F.mkVolumeMount (data-dir # volumes))
}
)
}
}
)
}

@ -4,35 +4,35 @@ let F = ../functions.dhall
let InputWeb = (../input.dhall).Web.Type
in \(app-name : Text)
-> \(input-web : InputWeb)
-> \(data-dir : List F.Volume.Type)
-> \(volumes : List F.Volume.Type)
-> \(env : List Kubernetes.EnvVar.Type)
-> F.KubernetesComponent::{
, Service = Some (F.mkService app-name "web" "api" 9000)
, Deployment = Some
( F.mkDeployment
app-name
F.Component::{
in \(app-name : Text) ->
\(input-web : InputWeb) ->
\(data-dir : List F.Volume.Type) ->
\(volumes : List F.Volume.Type) ->
\(env : List Kubernetes.EnvVar.Type) ->
F.KubernetesComponent::{
, Service = Some (F.mkService app-name "web" "api" 9000)
, Deployment = Some
( F.mkDeployment
app-name
F.Component::{
, name = "web"
, count = 1
, data-dir
, volumes
, container = Kubernetes.Container::{
, name = "web"
, count = 1
, data-dir = data-dir
, volumes = volumes
, container = Kubernetes.Container::{
, name = "web"
, image = input-web.image
, args = Some [ "zuul-web", "-d" ]
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "api"
, containerPort = 9000
}
]
, env = Some env
, volumeMounts = Some (F.mkVolumeMount (data-dir # volumes))
}
, image = input-web.image
, args = Some [ "zuul-web", "-d" ]
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "api"
, containerPort = 9000
}
]
, env = Some env
, volumeMounts = Some (F.mkVolumeMount (data-dir # volumes))
}
)
}
}
)
}

@ -10,41 +10,41 @@ let data-volumes =
, F.Volume::{ name = "zk-dat", dir = "/var/lib/zookeeper/" }
]
in \(app-name : Text)
-> \(client-conf : List F.Volume.Type)
-> F.KubernetesComponent::{
, Service = Some (F.mkService app-name "zk" "zk" 2281)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
in \(app-name : Text) ->
\(client-conf : List F.Volume.Type) ->
F.KubernetesComponent::{
, Service = Some (F.mkService app-name "zk" "zk" 2281)
, StatefulSet = Some
( F.mkStatefulSet
app-name
F.Component::{
, name = "zk"
, count = 1
, data-dir = data-volumes
, volumes = client-conf
, claim-size = 1
, container = Kubernetes.Container::{
, name = "zk"
, count = 1
, data-dir = data-volumes
, volumes = client-conf
, claim-size = 1
, container = Kubernetes.Container::{
, name = "zk"
, command = Some
[ "sh"
, "-c"
, "cp /conf-tls/zoo.cfg /conf/ && "
++ "cp /etc/zookeeper-tls/zk.pem /conf/zk.pem && "
++ "cp /etc/zookeeper-tls/ca.crt /conf/ca.pem && "
++ "chown zookeeper /conf/zoo.cfg /conf/zk.pem /conf/ca.pem && "
++ "exec /docker-entrypoint.sh zkServer.sh start-foreground"
]
, image = Some "docker.io/library/zookeeper"
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "zk"
, containerPort = 2281
}
]
, volumeMounts = Some
(F.mkVolumeMount (data-volumes # client-conf))
}
, command = Some
[ "sh"
, "-c"
, "cp /conf-tls/zoo.cfg /conf/ && "
++ "cp /etc/zookeeper-tls/zk.pem /conf/zk.pem && "
++ "cp /etc/zookeeper-tls/ca.crt /conf/ca.pem && "
++ "chown zookeeper /conf/zoo.cfg /conf/zk.pem /conf/ca.pem && "
++ "exec /docker-entrypoint.sh zkServer.sh start-foreground"
]
, image = Some "docker.io/library/zookeeper"
, imagePullPolicy = Some "IfNotPresent"
, ports = Some
[ Kubernetes.ContainerPort::{
, name = Some "zk"
, containerPort = 2281
}
]
, volumeMounts = Some
(F.mkVolumeMount (data-volumes # client-conf))
}
)
}
}
)
}

@ -2,10 +2,10 @@
TODO: replace opaque Text by structured zk host list and tls configuration
-}
\(zk-host : Text)
-> ''
${zk-host}
\(zk-host : Text) ->
''
${zk-host}
webapp:
port: 5000
''
webapp:
port: 5000
''

@ -1,20 +1,20 @@
{- This function converts a public-url Text to a registry.yaml file content
-}
\(public-url : Text)
-> ''
registry:
address: '0.0.0.0'
port: 9000
public-url: ${public-url}
tls-cert: /etc/zuul-registry/tls.crt
tls-key: /etc/zuul-registry/tls.key
secret: "%(ZUUL_REGISTRY_secret)"
storage:
driver: filesystem
root: /var/lib/zuul
users:
- name: "%(ZUUL_REGISTRY_username)"
pass: "%(ZUUL_REGISTRY_password)"
access: write
''
\(public-url : Text) ->
''
registry:
address: '0.0.0.0'
port: 9000
public-url: ${public-url}
tls-cert: /etc/zuul-registry/tls.crt
tls-key: /etc/zuul-registry/tls.key
secret: "%(ZUUL_REGISTRY_secret)"
storage:
driver: filesystem
root: /var/lib/zuul
users:
- name: "%(ZUUL_REGISTRY_username)"
pass: "%(ZUUL_REGISTRY_password)"
access: write
''

@ -1,23 +1,23 @@
{- This function converts a client-dir and server-dir Text to a zoo.cfg file content
-}
\(client-dir : Text)
-> \(server-dir : Text)
-> ''
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
server.1=0.0.0.0:2888:3888
\(client-dir : Text) ->
\(server-dir : Text) ->
''
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
server.1=0.0.0.0:2888:3888
# TLS configuration
secureClientPort=2281
serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
ssl.keyStore.location=${server-dir}/zk.pem
ssl.trustStore.location=${client-dir}/ca.pem
''
# TLS configuration
secureClientPort=2281
serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
ssl.keyStore.location=${server-dir}/zk.pem
ssl.trustStore.location=${client-dir}/ca.pem
''

@ -3,192 +3,190 @@
TODO: replace input schemas by the required attributes.
-}
\(input : (../input.dhall).Input.Type)
-> \(zk-hosts : Text)
-> let Prelude = ../../Prelude.dhall
let Schemas = ../input.dhall
let F = ../functions.dhall
let {- This is a high level method. It takes:
* a Connection type such as `Schemas.Gerrit.Type`,
* an Optional List of that type
* a function that goes from that type to a zuul.conf text blob
Then it returns a text blob for all the connections
-} mkConns =
\(type : Type)
-> \(list : Optional (List type))
-> \(f : type -> Text)
-> F.newlineSep
( merge
{ None = [] : List Text
, Some = Prelude.List.map type Text f
}
list
)
let merger-email =
F.defaultText input.merger.git_user_email "${input.name}@localhost"
let merger-user = F.defaultText input.merger.git_user_name "Zuul"
let executor-key-name = F.defaultText input.executor.ssh_key.key "id_rsa"
let sched-config = F.defaultText input.scheduler.config.key "main.yaml"
let web-url = F.defaultText input.web.status_url "http://web:9000"
let extra-kube-path = "/etc/nodepool-kubernetes/"
let db-uri =
merge
{ None = "postgresql://zuul:%(ZUUL_DB_PASSWORD)s@db/zuul"
, Some = \(some : Schemas.UserSecret.Type) -> "%(ZUUL_DB_URI)s"
}
input.database
let gerrits-conf =
mkConns
Schemas.Gerrit.Type
input.connections.gerrits
( \(gerrit : Schemas.Gerrit.Type)
-> let key = F.defaultText gerrit.sshkey.key "id_rsa"
let server = F.defaultText gerrit.server gerrit.name
in ''
[connection ${gerrit.name}]
driver=gerrit
server=${server}
sshkey=/etc/zuul-gerrit-${gerrit.name}/${key}
user=${gerrit.user}
baseurl=${gerrit.baseurl}
''
\(input : (../input.dhall).Input.Type) ->
\(zk-hosts : Text) ->
let Prelude = ../../Prelude.dhall
let Schemas = ../input.dhall
let F = ../functions.dhall
let {- This is a high level method. It takes:
* a Connection type such as `Schemas.Gerrit.Type`,
* an Optional List of that type
* a function that goes from that type to a zuul.conf text blob
Then it returns a text blob for all the connections
-} mkConns =
\(type : Type) ->
\(list : Optional (List type)) ->
\(f : type -> Text) ->
F.newlineSep
( merge
{ None = [] : List Text, Some = Prelude.List.map type Text f }
list
)
let githubs-conf =
mkConns
Schemas.GitHub.Type
input.connections.githubs
( \(github : Schemas.GitHub.Type)
-> let key = F.defaultText github.app_key.key "github_rsa"
in ''
[connection ${github.name}]
driver=github
server=github.com
app_id={github.app_id}
app_key=/etc/zuul-github-${github.name}/${key}
''
)
let merger-email =
F.defaultText input.merger.git_user_email "${input.name}@localhost"
let gits-conf =
mkConns
Schemas.Git.Type
input.connections.gits
( \(git : Schemas.Git.Type)
-> ''
[connection ${git.name}]
driver=git
baseurl=${git.baseurl}
let merger-user = F.defaultText input.merger.git_user_name "Zuul"
''
)
let executor-key-name = F.defaultText input.executor.ssh_key.key "id_rsa"
let mqtts-conf =
mkConns
Schemas.Mqtt.Type
input.connections.mqtts
( \(mqtt : Schemas.Mqtt.Type)
-> let user =
merge
{ None = "", Some = \(some : Text) -> "user=${some}" }
mqtt.user
let password =
merge
{ None = ""
, Some =
\(some : Schemas.UserSecret.Type)
-> "password=%(ZUUL_MQTT_PASSWORD)"
}
mqtt.password
in ''
[connection ${mqtt.name}]
driver=mqtt
server=${mqtt.server}
${user}
${password}
''
)
let sched-config = F.defaultText input.scheduler.config.key "main.yaml"
let job-volumes =
F.mkJobVolume
Text
( \(job-volume : Schemas.JobVolume.Type)
-> let {- TODO: add support for abritary lists of path per (context, access)
-} context =
merge
{ trusted = "trusted", untrusted = "untrusted" }
job-volume.context
let access =
merge
{ None = "ro"
, Some =
\(access : < ro | rw >)
-> merge { ro = "ro", rw = "rw" } access
}
job-volume.access
in "${context}_${access}_paths=${job-volume.path}"
)
input.jobVolumes
in ''
[gearman]
server=scheduler
ssl_ca=/etc/zuul-gearman/ca.crt
ssl_cert=/etc/zuul-gearman/tls.crt
ssl_key=/etc/zuul-gearman/tls.key
[gearman_server]
start=true
ssl_ca=/etc/zuul-gearman/ca.crt
ssl_cert=/etc/zuul-gearman/tls.crt
ssl_key=/etc/zuul-gearman/tls.key
[zookeeper]
${zk-hosts}
[merger]
git_user_email=${merger-email}
git_user_name=${merger-user}
[scheduler]
tenant_config=/etc/zuul-scheduler/${sched-config}
[web]
listen_address=0.0.0.0
root=${web-url}
[executor]
private_key_file=/etc/zuul-executor/${executor-key-name}
manage_ansible=false
''
++ Prelude.Text.concatSep "\n" job-volumes
++ ''
[connection "sql"]
driver=sql
dburi=${db-uri}
''
++ gits-conf
++ gerrits-conf
++ githubs-conf
++ mqtts-conf
let web-url = F.defaultText input.web.status_url "http://web:9000"
let extra-kube-path = "/etc/nodepool-kubernetes/"
let db-uri =
merge
{ None = "postgresql://zuul:%(ZUUL_DB_PASSWORD)s@db/zuul"
, Some = \(some : Schemas.UserSecret.Type) -> "%(ZUUL_DB_URI)s"
}
input.database
let gerrits-conf =
mkConns
Schemas.Gerrit.Type
input.connections.gerrits
( \(gerrit : Schemas.Gerrit.Type) ->
let key = F.defaultText gerrit.sshkey.key "id_rsa"
let server = F.defaultText gerrit.server gerrit.name
in ''
[connection ${gerrit.name}]
driver=gerrit
server=${server}
sshkey=/etc/zuul-gerrit-${gerrit.name}/${key}
user=${gerrit.user}
baseurl=${gerrit.baseurl}
''
)
let githubs-conf =
mkConns
Schemas.GitHub.Type
input.connections.githubs
( \(github : Schemas.GitHub.Type) ->
let key = F.defaultText github.app_key.key "github_rsa"
in ''
[connection ${github.name}]
driver=github
server=github.com
app_id={github.app_id}
app_key=/etc/zuul-github-${github.name}/${key}
''
)
let gits-conf =
mkConns
Schemas.Git.Type
input.connections.gits
( \(git : Schemas.Git.Type) ->
''
[connection ${git.name}]
driver=git
baseurl=${git.baseurl}
''
)
let mqtts-conf =
mkConns
Schemas.Mqtt.Type
input.connections.mqtts
( \(mqtt : Schemas.Mqtt.Type) ->
let user =
merge
{ None = "", Some = \(some : Text) -> "user=${some}" }
mqtt.user
let password =
merge
{ None = ""
, Some =
\(some : Schemas.UserSecret.Type) ->
"password=%(ZUUL_MQTT_PASSWORD)"
}
mqtt.password
in ''
[connection ${mqtt.name}]
driver=mqtt
server=${mqtt.server}
${user}
${password}
''
)
let job-volumes =
F.mkJobVolume
Text
( \(job-volume : Schemas.JobVolume.Type) ->
let {- TODO: add support for abritary lists of path per (context, access)
-} context =
merge
{ trusted = "trusted", untrusted = "untrusted" }
job-volume.context
let access =
merge
{ None = "ro"
, Some =
\(access : < ro | rw >) ->
merge { ro = "ro", rw = "rw" } access
}
job-volume.access
in "${context}_${access}_paths=${job-volume.path}"
)
input.jobVolumes
in ''
[gearman]
server=scheduler
ssl_ca=/etc/zuul-gearman/ca.crt
ssl_cert=/etc/zuul-gearman/tls.crt
ssl_key=/etc/zuul-gearman/tls.key
[gearman_server]
start=true
ssl_ca=/etc/zuul-gearman/ca.crt
ssl_cert=/etc/zuul-gearman/tls.crt
ssl_key=/etc/zuul-gearman/tls.key
[zookeeper]
${zk-hosts}
[merger]
git_user_email=${merger-email}
git_user_name=${merger-user}
[scheduler]
tenant_config=/etc/zuul-scheduler/${sched-config}
[web]
listen_address=0.0.0.0
root=${web-url}
[executor]
private_key_file=/etc/zuul-executor/${executor-key-name}
manage_ansible=false
''
++ Prelude.Text.concatSep "\n" job-volumes
++ ''
[connection "sql"]
driver=sql
dburi=${db-uri}
''
++ gits-conf
++ gerrits-conf
++ githubs-conf
++ mqtts-conf

@ -16,86 +16,85 @@ let {- This methods process the optional input.job-volumes list. It takes:
Then it returns a list of the output type
-} mkJobVolume =
\(OutputType : Type)
-> \(f : JobVolume -> OutputType)
-> \(job-volumes : Optional (List JobVolume))
-> merge
{ None = [] : List OutputType
, Some = Prelude.List.map JobVolume OutputType f
}
job-volumes
\(OutputType : Type) ->
\(f : JobVolume -> OutputType) ->
\(job-volumes : Optional (List JobVolume)) ->
merge
{ None = [] : List OutputType
, Some = Prelude.List.map JobVolume OutputType f
}
job-volumes
let defaultNat =
\(value : Optional Natural)
-> \(default : Natural)
-> merge { None = default, Some = \(some : Natural) -> some } value
\(value : Optional Natural) ->
\(default : Natural) ->
merge { None = default, Some = \(some : Natural) -> some } value
let defaultText =
\(value : Optional Text)
-> \(default : Text)
-> merge { None = default, Some = \(some : Text) -> some } value
\(value : Optional Text) ->
\(default : Text) ->
merge { None = default, Some = \(some : Text) -> some } value
let defaultKey =
\(secret : Optional UserSecret)
-> \(default : Text)
-> merge
{ None = default
, Some = \(some : UserSecret) -> defaultText some.key default
}
secret
\(secret : Optional UserSecret) ->
\(default : Text) ->
merge
{ None = default
, Some = \(some : UserSecret) -> defaultText some.key default
}
secret
let mkAppLabels =
\(app-name : Text)
-> [ { mapKey = "app.kubernetes.io/name", mapValue = app-name }
, { mapKey = "app.kubernetes.io/instance", mapValue = app-name }
, { mapKey = "app.kubernetes.io/part-of", mapValue = "zuul" }
]
\(app-name : Text) ->
[ { mapKey = "app.kubernetes.io/name", mapValue = app-name }
, { mapKey = "app.kubernetes.io/instance", mapValue = app-name }
, { mapKey = "app.kubernetes.io/part-of", mapValue = "zuul" }
]
let mkComponentLabel =
\(app-name : Text)
-> \(component-name : Text)
-> mkAppLabels app-name
# [ { mapKey = "app.kubernetes.io/component"
, mapValue = component-name
}
]
\(app-name : Text) ->
\(component-name : Text) ->
mkAppLabels app-name
# [ { mapKey = "app.kubernetes.io/component"
, mapValue = component-name
}
]
let Label = { mapKey : Text, mapValue : Text }
let Labels = List Label
let mkObjectMeta =
\(name : Text)
-> \(labels : Labels)
-> Kubernetes.ObjectMeta::{ name = name, labels = Some labels }
\(name : Text) ->
\(labels : Labels) ->
Kubernetes.ObjectMeta::{ name, labels = Some labels }
let mkSelector =
\(labels : Labels)
-> Kubernetes.LabelSelector::{ matchLabels = Some labels }
\(labels : Labels) ->
Kubernetes.LabelSelector::{ matchLabels = Some labels }
let mkService =
\(app-name : Text)
-> \(name : Text)
-> \(port-name : Text)
-> \(port : Natural)
-> let labels = mkComponentLabel app-name name
in Kubernetes.Service::{
, metadata = mkObjectMeta name labels
, spec = Some Kubernetes.ServiceSpec::{
, type = Some "ClusterIP"
, selector = Some labels
, ports = Some
[ Kubernetes.ServicePort::{
, name = Some port-name
, protocol = Some "TCP"
, targetPort = Some
(Kubernetes.IntOrString.String port-name)
, port = port
}
]
}
\(app-name : Text) ->
\(name : Text) ->
\(port-name : Text) ->
\(port : Natural) ->
let labels = mkComponentLabel app-name name
in Kubernetes.Service::{
, metadata = mkObjectMeta name labels
, spec = Some Kubernetes.ServiceSpec::{
, type = Some "ClusterIP"
, selector = Some labels
, ports = Some
[ Kubernetes.ServicePort::{
, name = Some port-name
, protocol = Some "TCP"
, targetPort = Some (Kubernetes.IntOrString.String port-name)
, port
}
]
}
}
let EnvSecret = { name : Text, secret : Text, key : Text }
@ -118,11 +117,11 @@ let {- A high level description of a component such as the scheduler or the laun
, claim-size : Natural
}
, default =
{ data-dir = [] : List Volume.Type
, volumes = [] : List Volume.Type
, extra-volumes = [] : List Kubernetes.Volume.Type
, claim-size = 0
}
{ data-dir = [] : List Volume.Type
, volumes = [] : List Volume.Type
, extra-volumes = [] : List Kubernetes.Volume.Type
, claim-size = 0
}
}
let {- The Kubernetes resources of a Component
@ -133,169 +132,163 @@ let {- The Kubernetes resources of a Component
, StatefulSet : Optional Kubernetes.StatefulSet.Type
}
, default =
{ Service = None Kubernetes.Service.Type
, Deployment = None Kubernetes.Deployment.Type
, StatefulSet = None Kubernetes.StatefulSet.Type
}
{ Service = None Kubernetes.Service.Type
, Deployment = None Kubernetes.Deployment.Type
, StatefulSet = None Kubernetes.StatefulSet.Type
}
}
let mkVolumeEmptyDir =
Prelude.List.map
Volume.Type
Kubernetes.Volume.Type
( \(volume : Volume.Type)
-> Kubernetes.Volume::{
, name = volume.name
, emptyDir = Some Kubernetes.EmptyDirVolumeSource::{=}
}
( \(volume : Volume.Type) ->
Kubernetes.Volume::{
, name = volume.name
, emptyDir = Some Kubernetes.EmptyDirVolumeSource::{=}
}
)
let mkVolumeSecret =
Prelude.List.map
Volume.Type
Kubernetes.Volume.Type
( \(volume : Volume.Type)
-> Kubernetes.Volume::{
, name = volume.name
, secret = Some Kubernetes.SecretVolumeSource::{
, secretName = Some volume.name
, defaultMode = Some 256
}
( \(volume : Volume.Type) ->
Kubernetes.Volume::{
, name = volume.name
, secret = Some Kubernetes.SecretVolumeSource::{
, secretName = Some volume.name
, defaultMode = Some 256
}
}
)
let mkPodTemplateSpec =
\(component : Component.Type)
-> \(labels : Labels)
-> Kubernetes.PodTemplateSpec::{
, metadata = mkObjectMeta component.name labels
, spec = Some Kubernetes.PodSpec::{
, volumes = Some
( mkVolumeSecret component.volumes
# mkVolumeEmptyDir component.data-dir
# component.extra-volumes
)
, containers = [ component.container ]
, automountServiceAccountToken = Some False
}
\(component : Component.Type) ->
\(labels : Labels) ->
Kubernetes.PodTemplateSpec::{
, metadata = mkObjectMeta component.name labels
, spec = Some Kubernetes.PodSpec::{
, volumes = Some
( mkVolumeSecret component.volumes
# mkVolumeEmptyDir component.data-dir
# component.extra-volumes
)
, containers = [ component.container ]
, automountServiceAccountToken = Some False
}
}
let mkStatefulSet =
\(app-name : Text)
-> \(component : Component.Type)
-> let labels = mkComponentLabel app-name component.name
let component-name = app-name ++ "-" ++ component.name
let claim =
if Natural/isZero component.claim-size
then [] : List Kubernetes.PersistentVolumeClaim.Type
else [ Kubernetes.PersistentVolumeClaim::{
, apiVersion = ""
, kind = ""
, metadata = Kubernetes.ObjectMeta::{
, name = component-name
}
, spec = Some Kubernetes.PersistentVolumeClaimSpec::{
, accessModes = Some [ "ReadWriteOnce" ]
, resources = Some Kubernetes.ResourceRequirements::{
, requests = Some
( toMap
{ storage =
Natural/show component.claim-size
++ "Gi"
}
)
}
\(app-name : Text) ->
\(component : Component.Type) ->
let labels = mkComponentLabel app-name component.name
let component-name = app-name ++ "-" ++ component.name
let claim =
if Natural/isZero component.claim-size
then [] : List Kubernetes.PersistentVolumeClaim.Type
else [ Kubernetes.PersistentVolumeClaim::{
, apiVersion = ""
, kind = ""
, metadata = Kubernetes.ObjectMeta::{
, name = component-name
}
, spec = Some Kubernetes.PersistentVolumeClaimSpec::{
, accessModes = Some [ "ReadWriteOnce" ]
, resources = Some Kubernetes.ResourceRequirements::{
, requests = Some
( toMap
{ storage =
Natural/show component.claim-size ++ "Gi"
}
)
}
}
]
in Kubernetes.StatefulSet::{
, metadata = mkObjectMeta component-name labels
, spec = Some Kubernetes.StatefulSetSpec::{
, serviceName = component.name
, replicas = Some component.count
, selector = mkSelector labels
, template = mkPodTemplateSpec component labels
, volumeClaimTemplates = Some claim
}
}
]
in Kubernetes.StatefulSet::{
, metadata = mkObjectMeta component-name labels
, spec = Some Kubernetes.StatefulSetSpec::{
, serviceName = component.name
, replicas = Some component.count
, selector = mkSelector labels
, template = mkPodTemplateSpec component labels
, volumeClaimTemplates = Some claim
}
}
let mkDeployment =
\(app-name : Text)
-> \(component : Component.Type)
-> let labels = mkComponentLabel app-name component.name
let component-name = app-name ++ "-" ++ component.name
in Kubernetes.Deployment::{
, metadata = mkObjectMeta component-name labels
, spec = Some Kubernetes.DeploymentSpec::{
, replicas = Some component.count
, selector = mkSelector labels
, template = mkPodTemplateSpec component labels
}
\(app-name : Text) ->
\(component : Component.Type) ->
let labels = mkComponentLabel app-name component.name
let component-name = app-name ++ "-" ++ component.name
in Kubernetes.Deployment::{
, metadata = mkObjectMeta component-name labels
, spec = Some Kubernetes.DeploymentSpec::{
, replicas = Some component.count
, selector = mkSelector labels
, template = mkPodTemplateSpec component labels
}
}
let mkEnvVarValue =
Prelude.List.map
Label
Kubernetes.EnvVar.Type
( \(env : Label)
-> Kubernetes.EnvVar::{
, name = env.mapKey
, value = Some env.mapValue
}
( \(env : Label) ->
Kubernetes.EnvVar::{ name = env.mapKey, value = Some env.mapValue }
)
let mkEnvVarSecret =
Prelude.List.map
EnvSecret
Kubernetes.EnvVar.Type
( \(env : EnvSecret)
-> Kubernetes.EnvVar::{
, name = env.name
, valueFrom = Some Kubernetes.EnvVarSource::{
, secretKeyRef = Some Kubernetes.SecretKeySelector::{
, key = env.key
, name = Some env.secret
}
( \(env : EnvSecret) ->
Kubernetes.EnvVar::{
, name = env.name
, valueFrom = Some Kubernetes.EnvVarSource::{
, secretKeyRef = Some Kubernetes.SecretKeySelector::{
, key = env.key
, name = Some env.secret
}
}
}
)
let mkVolumeMount =
Prelude.List.map
Volume.Type
Kubernetes.VolumeMount.Type
( \(volume : Volume.Type)
-> Kubernetes.VolumeMount::{
, name = volume.name
, mountPath = volume.dir
}
( \(volume : Volume.Type) ->
Kubernetes.VolumeMount::{
, name = volume.name
, mountPath = volume.dir
}
)
in { defaultNat = defaultNat
, defaultText = defaultText
, defaultKey = defaultKey
in { default