diff --git a/Prelude b/Prelude new file mode 100644 index 00000000..7421d1fe --- /dev/null +++ b/Prelude @@ -0,0 +1 @@ +https://raw.githubusercontent.com/dhall-lang/Prelude/v3.0.0/package.dhall sha256:990c936c6dba21bc516c5d91a69afd908dce8c8698d6c0912798aa4ad1b978f3 diff --git a/api/Deployment/Container b/api/Container/Container similarity index 50% rename from api/Deployment/Container rename to api/Container/Container index 5bb77445..a9f269d5 100644 --- a/api/Deployment/Container +++ b/api/Container/Container @@ -4,10 +4,10 @@ , imagePullPolicy : Text , minCPU : Natural , maxCPU : Natural -, mounts : List ./Mount +, mounts : List (../common/types).Mount , envVars : List { mapKey : Text, mapValue : Text } -, port : Optional Natural -, command : Optional (List Text) -, livenessProbe : Optional ./Probe -, readinessProbe : Optional ./Probe +, ports : List Natural +, command : List Text +, livenessProbe : Optional (../common/types).Probe +, readinessProbe : Optional (../common/types).Probe } diff --git a/api/Container/default b/api/Container/default new file mode 100644 index 00000000..67179b74 --- /dev/null +++ b/api/Container/default @@ -0,0 +1,13 @@ +{ name = "CHANGEME" +, imageName = "SOME_IMAGE" +, imageTag = "0.1" +, imagePullPolicy = "Always" +, minCPU = 10 +, maxCPU = 500 +, mounts = [] : List (../common/types).Mount +, envVars = [] : List { mapKey : Text, mapValue : Text } +, ports = [] : List Natural +, command = [] : List Text +, livenessProbe = [] : Optional (../common/types).Probe +, readinessProbe = [] : Optional (../common/types).Probe +} : ./Container diff --git a/api/Container/mkContainer b/api/Container/mkContainer new file mode 100644 index 00000000..c9f37d74 --- /dev/null +++ b/api/Container/mkContainer @@ -0,0 +1,74 @@ +let Prelude = ../../Prelude +in let map = Prelude.`List`.map +in let Opt/map = Prelude.`Optional`.map +in let kv = Prelude.JSON.keyText +in let types = ../common/types +in let defaults = ../common/defaults + +in let mkEnvVar : types.KV → types.EnvVar = + + λ(var : types.KV) → + + defaults.envVar + { name = var.mapKey } // + { value = Some var.mapValue } + + +in let mkMount : types.Mount → types.MountRaw = + + λ(mount : types.Mount) → + + defaults.mount + { mountPath = mount.mountPath + , name = mount.name + } // + { readOnly = mount.readOnly } + + +in let mkContainerPort : Natural → types.ContainerPort = + + λ(port : Natural) → + + defaults.containerPort + { containerPort = port } + + +in let mkProbe : types.Probe → types.ProbeRaw = + + λ(probe : types.Probe) → + + defaults.probe // + { initialDelaySeconds = Some probe.initial + , periodSeconds = Some probe.period + , httpGet = Some + (defaults.httpGet + { port = defaults.Int probe.port } // + { path = Some probe.path }) + } + + +in let mkContainer : ./Container → types.Container = + + λ(container : ./Container) → + + defaults.container + { name = container.name } // + { image = Some "${container.imageName}:${container.imageTag}" + , imagePullPolicy = Some container.imagePullPolicy + , ports = Some + (map Natural types.ContainerPort mkContainerPort container.ports) + , resources = Some + { limits = Some [kv "cpu" "${Natural/show container.maxCPU}m"] + , requests = Some [kv "cpu" "${Natural/show container.minCPU}m"] + } + , command = Some container.command + , env = Some (map types.KV types.EnvVar mkEnvVar container.envVars) + , volumeMounts = Some (map types.Mount types.MountRaw mkMount container.mounts) + -- Poll the container to see if the it's alive or we should restart it + , livenessProbe = (Opt/map types.Probe types.ProbeRaw mkProbe container.livenessProbe) + -- Poll the container to see that it's ready for requests + , readinessProbe = (Opt/map types.Probe types.ProbeRaw mkProbe container.readinessProbe) + } + + +in mkContainer diff --git a/api/CronJob/CronJob b/api/CronJob/CronJob new file mode 100644 index 00000000..e3cb3883 --- /dev/null +++ b/api/CronJob/CronJob @@ -0,0 +1,4 @@ +{ name : Text +, schedule : Text +, containers : List ../Container/Container +} diff --git a/api/CronJob/RawDefaults b/api/CronJob/RawDefaults index cc55809f..91a10311 100644 --- a/api/CronJob/RawDefaults +++ b/api/CronJob/RawDefaults @@ -2,7 +2,5 @@ , spec = ../../default/io.k8s.api.batch.v1beta1.CronJobSpec.dhall , jobSpec = ../../default/io.k8s.api.batch.v1.JobSpec.dhall , podSpec = ../../default/io.k8s.api.core.v1.PodSpec.dhall -, container = ../../default/io.k8s.api.core.v1.Container.dhall -, envVar = ../../default/io.k8s.api.core.v1.EnvVar.dhall , meta = ../../default/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta.dhall -} \ No newline at end of file +} // ../common/defaults diff --git a/api/CronJob/RawTypes b/api/CronJob/RawTypes index 01ec3e1d..1e1c84d7 100644 --- a/api/CronJob/RawTypes +++ b/api/CronJob/RawTypes @@ -1,6 +1,5 @@ -{ CronJob = ../../types/io.k8s.api.batch.v1beta1.CronJob.dhall -, Spec = ../../types/io.k8s.api.batch.v1beta1.CronJobSpec.dhall -, JobSpec = ../../types/io.k8s.api.batch.v1.JobSpec.dhall -, PodSpec = ../../types/io.k8s.api.core.v1.PodSpec.dhall -, EnvVar = ../../types/io.k8s.api.core.v1.EnvVar.dhall -} \ No newline at end of file +{ CronJob = ../../types/io.k8s.api.batch.v1beta1.CronJob.dhall +, Spec = ../../types/io.k8s.api.batch.v1beta1.CronJobSpec.dhall +, JobSpec = ../../types/io.k8s.api.batch.v1.JobSpec.dhall +, PodSpec = ../../types/io.k8s.api.core.v1.PodSpec.dhall +} // ../common/types diff --git a/api/CronJob/mkCronJob b/api/CronJob/mkCronJob new file mode 100644 index 00000000..9d8cc831 --- /dev/null +++ b/api/CronJob/mkCronJob @@ -0,0 +1,37 @@ +let map = (../../Prelude).`List`.map + +-- Kubernetes types and defaults +in let Types = ./RawTypes +in let default = ./RawDefaults + + +in let mkCronJob : ./CronJob → Types.CronJob = + + λ(cronjob : ./CronJob) → + + let spec = default.spec + { schedule = cronjob.schedule + , jobTemplate = + { metadata = default.meta { name = cronjob.name } + , spec = Some (default.jobSpec + { template = + { metadata = default.meta { name = cronjob.name } + , spec = Some (default.podSpec + { containers = map + ../Container/Container + Types.Container + ../Container/mkContainer + cronjob.containers + } // { restartPolicy = Some "OnFailure" }) + } + } // { backoffLimit = Some 2 }) + } + } + + in default.cronjob + { metadata = default.meta { name = cronjob.name } + } // + { spec = Some spec } : Types.CronJob + + +in mkCronJob diff --git a/api/Deployment/RawDefaults b/api/Deployment/RawDefaults index cfa25067..8ee98bf8 100644 --- a/api/Deployment/RawDefaults +++ b/api/Deployment/RawDefaults @@ -1,6 +1,6 @@ -let intOrString = ../../default/io.k8s.apimachinery.pkg.util.intstr.IntOrString.dhall -in +let IntOrString = ../../types/io.k8s.apimachinery.pkg.util.intstr.IntOrString.dhall +in { deployment = ../../default/io.k8s.api.apps.v1.Deployment.dhall , container = ../../default/io.k8s.api.core.v1.Container.dhall , containerPort = ../../default/io.k8s.api.core.v1.ContainerPort.dhall @@ -17,7 +17,6 @@ in , pathVolume = ../../default/io.k8s.api.core.v1.HostPathVolumeSource.dhall , meta = ../../default/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta.dhall , selector = ../../default/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector.dhall -, intOrString = intOrString -, Int = intOrString.Int -, String = intOrString.String -} \ No newline at end of file +, Int = IntOrString.Int +, String = IntOrString.String +} diff --git a/api/Deployment/RawTypes b/api/Deployment/RawTypes index cfbd70b9..6a4987c7 100644 --- a/api/Deployment/RawTypes +++ b/api/Deployment/RawTypes @@ -1,3 +1,5 @@ +../common/types +// { Deployment = ../../types/io.k8s.api.apps.v1.Deployment.dhall , Container = ../../types/io.k8s.api.core.v1.Container.dhall , ContainerPort = ../../types/io.k8s.api.core.v1.ContainerPort.dhall diff --git a/api/Deployment/defaultContainer b/api/Deployment/defaultContainer deleted file mode 100644 index 6c38ca6e..00000000 --- a/api/Deployment/defaultContainer +++ /dev/null @@ -1,13 +0,0 @@ -{ name = "CHANGEME" -, imageName = "SOME_IMAGE" -, imageTag = "0.1" -, imagePullPolicy = "Always" -, minCPU = 10 -, maxCPU = 500 -, mounts = [] : List ./Mount -, envVars = [] : List { mapKey : Text, mapValue : Text } -, port = [] : Optional Natural -, command = [] : Optional (List Text) -, livenessProbe = [] : Optional ./Probe -, readinessProbe = [] : Optional ./Probe -} : ./Container \ No newline at end of file diff --git a/api/common/KV b/api/common/KV new file mode 100644 index 00000000..a4635990 --- /dev/null +++ b/api/common/KV @@ -0,0 +1 @@ +{ mapKey : Text, mapValue : Text } diff --git a/api/Deployment/Mount b/api/common/Mount similarity index 100% rename from api/Deployment/Mount rename to api/common/Mount diff --git a/api/Deployment/Probe b/api/common/Probe similarity index 100% rename from api/Deployment/Probe rename to api/common/Probe diff --git a/api/common/defaults b/api/common/defaults new file mode 100644 index 00000000..7a30e245 --- /dev/null +++ b/api/common/defaults @@ -0,0 +1,12 @@ +let IntOrString = ../../types/io.k8s.apimachinery.pkg.util.intstr.IntOrString.dhall +in + +{ container = ../../default/io.k8s.api.core.v1.Container.dhall +, containerPort = ../../default/io.k8s.api.core.v1.ContainerPort.dhall +, probe = ../../default/io.k8s.api.core.v1.Probe.dhall +, httpGet = ../../default/io.k8s.api.core.v1.HTTPGetAction.dhall +, envVar = ../../default/io.k8s.api.core.v1.EnvVar.dhall +, mount = ../../default/io.k8s.api.core.v1.VolumeMount.dhall +, Int = IntOrString.Int +, String = IntOrString.String +} diff --git a/api/common/types b/api/common/types new file mode 100644 index 00000000..cce7caad --- /dev/null +++ b/api/common/types @@ -0,0 +1,11 @@ +{ HttpGet = ../../types/io.k8s.api.core.v1.HTTPGetAction.dhall +, Container = ../../types/io.k8s.api.core.v1.Container.dhall +, ContainerPort = ../../types/io.k8s.api.core.v1.ContainerPort.dhall +, EnvVar = ../../types/io.k8s.api.core.v1.EnvVar.dhall +, IntOrString = ../../types/io.k8s.apimachinery.pkg.util.intstr.IntOrString.dhall +, MountRaw = ../../types/io.k8s.api.core.v1.VolumeMount.dhall +, ProbeRaw = ../../types/io.k8s.api.core.v1.Probe.dhall +, Mount = ./Mount +, Probe = ./Probe +, KV = ./KV +} diff --git a/api/defaults.dhall b/api/defaults.dhall new file mode 100644 index 00000000..bb0852a8 --- /dev/null +++ b/api/defaults.dhall @@ -0,0 +1,28 @@ +-- This first chunks is in sync with the types.dhall file +{ container = ../default/io.k8s.api.core.v1.Container.dhall +, containerPort = ../default/io.k8s.api.core.v1.ContainerPort.dhall +, cronJob = ../default/io.k8s.api.batch.v1beta1.CronJob.dhall +, cronJobSpec = ../default/io.k8s.api.batch.v1beta1.CronJobSpec.dhall +, deployment = ../default/io.k8s.api.apps.v1.Deployment.dhall +, deploymentSpec = ../default/io.k8s.api.apps.v1.DeploymentSpec.dhall +, deploymentStrategy = ../default/io.k8s.api.apps.v1.DeploymentStrategy.dhall +, emptyVolume = ../default/io.k8s.api.core.v1.EmptyDirVolumeSource.dhall +, envVar = ../default/io.k8s.api.core.v1.EnvVar.dhall +, httpGet = ../default/io.k8s.api.core.v1.HTTPGetAction.dhall +, int = (../default/io.k8s.apimachinery.pkg.util.intstr.IntOrString.dhall).Int +, jobSpec = ../default/io.k8s.api.batch.v1.JobSpec.dhall +, pathVolume = ../default/io.k8s.api.core.v1.HostPathVolumeSource.dhall +, podSpec = ../default/io.k8s.api.core.v1.PodSpec.dhall +, probe = ../default/io.k8s.api.core.v1.Probe.dhall +, resources = ../default/io.k8s.api.core.v1.ResourceRequirements.dhall +, rollingUpdate = ../default/io.k8s.api.apps.v1.RollingUpdateDeployment.dhall +, secretVolume = ../default/io.k8s.api.core.v1.SecretVolumeSource.dhall +, service = ../default/io.k8s.api.core.v1.Service.dhall +, servicePort = ../default/io.k8s.api.core.v1.ServicePort.dhall +, serviceSpec = ../default/io.k8s.api.core.v1.ServiceSpec.dhall +, string = (../default/io.k8s.apimachinery.pkg.util.intstr.IntOrString.dhall).String +, volume = ../default/io.k8s.api.core.v1.Volume.dhall +, volumeMount = ../default/io.k8s.api.core.v1.VolumeMount.dhall + +, meta = ../default/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta.dhall +} diff --git a/api/types.dhall b/api/types.dhall new file mode 100644 index 00000000..61b67afb --- /dev/null +++ b/api/types.dhall @@ -0,0 +1,24 @@ +{ Container = ../types/io.k8s.api.core.v1.Container.dhall +, ContainerPort = ../types/io.k8s.api.core.v1.ContainerPort.dhall +, CronJob = ../types/io.k8s.api.batch.v1beta1.CronJob.dhall +, CronJobSpec = ../types/io.k8s.api.batch.v1beta1.CronJobSpec.dhall +, Deployment = ../types/io.k8s.api.apps.v1.Deployment.dhall +, DeploymentSpec = ../types/io.k8s.api.apps.v1.DeploymentSpec.dhall +, DeploymentStrategy = ../types/io.k8s.api.apps.v1.DeploymentStrategy.dhall +, EmptyVolume = ../types/io.k8s.api.core.v1.EmptyDirVolumeSource.dhall +, EnvVar = ../types/io.k8s.api.core.v1.EnvVar.dhall +, HttpGet = ../types/io.k8s.api.core.v1.HTTPGetAction.dhall +, IntOrString = ../types/io.k8s.apimachinery.pkg.util.intstr.IntOrString.dhall +, JobSpec = ../types/io.k8s.api.batch.v1.JobSpec.dhall +, PathVolume = ../types/io.k8s.api.core.v1.HostPathVolumeSource.dhall +, PodSpec = ../types/io.k8s.api.core.v1.PodSpec.dhall +, Probe = ../types/io.k8s.api.core.v1.Probe.dhall +, Resources = ../types/io.k8s.api.core.v1.ResourceRequirements.dhall +, RollingUpdate = ../types/io.k8s.api.apps.v1.RollingUpdateDeployment.dhall +, SecretVolume = ../types/io.k8s.api.core.v1.SecretVolumeSource.dhall +, Service = ../types/io.k8s.api.core.v1.Service.dhall +, ServicePort = ../types/io.k8s.api.core.v1.ServicePort.dhall +, ServiceSpec = ../types/io.k8s.api.core.v1.ServiceSpec.dhall +, Volume = ../types/io.k8s.api.core.v1.Volume.dhall +, VolumeMount = ../types/io.k8s.api.core.v1.VolumeMount.dhall +}