Description
yaml-to-dhall
seems to simply strip leading 0
's from octal values when converting them to dhall. This leads to problems when we need to render the dhall back to yaml again.
Consider the following Kubernetes Deployment yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
description: Collects metrics and aggregates them into graphs.
labels:
deploy: sourcegraph
sourcegraph-resource-requires: no-cluster-admin
name: prometheus
spec:
minReadySeconds: 10
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: prometheus
strategy:
type: Recreate
template:
metadata:
labels:
deploy: sourcegraph
app: prometheus
spec:
containers:
- image: index.docker.io/sourcegraph/prometheus:3.18.0@sha256:e970ed46bdf3f73477f95de9ada424ada4a24505239687ce0e474a62dac6c67b
terminationMessagePolicy: FallbackToLogsOnError
name: prometheus
readinessProbe:
httpGet:
path: /-/ready
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
livenessProbe:
httpGet:
path: /-/healthy
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
ports:
- containerPort: 9090
name: http
volumeMounts:
- mountPath: /prometheus
name: data
- mountPath: /sg_prometheus_add_ons
name: config
# Prometheus is relied upon to monitor services for sending alerts to site admins when
# something is wrong with Sourcegraph, thus its memory requests and limits are the same to
# guarantee it has enough memory to perform its job reliably and prevent conflicts with
# other pods on the same host node.
#
# Its average memory usage may be much lower than 3G if Sourcegraph itself does not have
# much traffic, the 3G number chosen here is what works reliably on Sourcegraph.com with
# lots of traffic.
resources:
limits:
cpu: "2"
memory: 3G
requests:
cpu: 500m
memory: 3G
securityContext:
runAsUser: 0
serviceAccountName: prometheus
volumes:
- name: data
persistentVolumeClaim:
claimName: prometheus
- configMap:
defaultMode: 0777
name: prometheus
name: config
Note the defaultMode
of the configMap, 0777
(octal)
- configMap:
defaultMode: 0777
name: prometheus
name: config
Converting it to dhall results in the following output
> yaml-to-dhall --version
1.2.1
> pbpaste | yaml-to-dhall '( https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/f4bf4b9ddf669f7149ec32150863a93d6c4b3ef1/1.18/schemas/io.k8s.api.apps.v1.Deployment.dhall ).Type'
{ apiVersion = "apps/v1"
, kind = "Deployment"
, metadata =
{ annotations = Some
( toMap
{ description = "Collects metrics and aggregates them into graphs." }
)
, clusterName = None Text
, creationTimestamp = None Text
, deletionGracePeriodSeconds = None Natural
, deletionTimestamp = None Text
, finalizers = None (List Text)
, generateName = None Text
, generation = None Natural
, labels = Some
( toMap
{ sourcegraph-resource-requires = "no-cluster-admin"
, deploy = "sourcegraph"
}
)
, managedFields =
None
( List
{ apiVersion : Text
, fieldsType : Optional Text
, fieldsV1 : Optional (List { mapKey : Text, mapValue : Text })
, manager : Optional Text
, operation : Optional Text
, time : Optional Text
}
)
, name = Some "prometheus"
, namespace = None Text
, ownerReferences =
None
( List
{ apiVersion : Text
, blockOwnerDeletion : Optional Bool
, controller : Optional Bool
, kind : Text
, name : Text
, uid : Text
}
)
, resourceVersion = None Text
, selfLink = None Text
, uid = None Text
}
, spec = Some
{ minReadySeconds = Some 10
, paused = None Bool
, progressDeadlineSeconds = None Natural
, replicas = Some 1
, revisionHistoryLimit = Some 10
, selector =
{ matchExpressions =
None
(List { key : Text, operator : Text, values : Optional (List Text) })
, matchLabels = Some (toMap { app = "prometheus" })
}
, strategy = Some
{ rollingUpdate =
None
{ maxSurge : Optional < Int : Natural | String : Text >
, maxUnavailable : Optional < Int : Natural | String : Text >
}
, type = Some "Recreate"
}
, template =
{ metadata =
{ annotations = None (List { mapKey : Text, mapValue : Text })
, clusterName = None Text
, creationTimestamp = None Text
, deletionGracePeriodSeconds = None Natural
, deletionTimestamp = None Text
, finalizers = None (List Text)
, generateName = None Text
, generation = None Natural
, labels = Some (toMap { app = "prometheus", deploy = "sourcegraph" })
, managedFields =
None
( List
{ apiVersion : Text
, fieldsType : Optional Text
, fieldsV1 : Optional (List { mapKey : Text, mapValue : Text })
, manager : Optional Text
, operation : Optional Text
, time : Optional Text
}
)
, name = None Text
, namespace = None Text
, ownerReferences =
None
( List
{ apiVersion : Text
, blockOwnerDeletion : Optional Bool
, controller : Optional Bool
, kind : Text
, name : Text
, uid : Text
}
)
, resourceVersion = None Text
, selfLink = None Text
, uid = None Text
}
, spec = Some
{ activeDeadlineSeconds = None Natural
, affinity =
None
{ nodeAffinity :
Optional
{ preferredDuringSchedulingIgnoredDuringExecution :
Optional
( List
{ preference :
{ matchExpressions :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
, matchFields :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
}
, weight : Natural
}
)
, requiredDuringSchedulingIgnoredDuringExecution :
Optional
{ nodeSelectorTerms :
List
{ matchExpressions :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
, matchFields :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
}
}
}
, podAffinity :
Optional
{ preferredDuringSchedulingIgnoredDuringExecution :
Optional
( List
{ podAffinityTerm :
{ labelSelector :
Optional
{ matchExpressions :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
, matchLabels :
Optional
( List
{ mapKey : Text
, mapValue : Text
}
)
}
, namespaces : Optional (List Text)
, topologyKey : Text
}
, weight : Natural
}
)
, requiredDuringSchedulingIgnoredDuringExecution :
Optional
( List
{ labelSelector :
Optional
{ matchExpressions :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
, matchLabels :
Optional
( List
{ mapKey : Text, mapValue : Text }
)
}
, namespaces : Optional (List Text)
, topologyKey : Text
}
)
}
, podAntiAffinity :
Optional
{ preferredDuringSchedulingIgnoredDuringExecution :
Optional
( List
{ podAffinityTerm :
{ labelSelector :
Optional
{ matchExpressions :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
, matchLabels :
Optional
( List
{ mapKey : Text
, mapValue : Text
}
)
}
, namespaces : Optional (List Text)
, topologyKey : Text
}
, weight : Natural
}
)
, requiredDuringSchedulingIgnoredDuringExecution :
Optional
( List
{ labelSelector :
Optional
{ matchExpressions :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
, matchLabels :
Optional
( List
{ mapKey : Text, mapValue : Text }
)
}
, namespaces : Optional (List Text)
, topologyKey : Text
}
)
}
}
, automountServiceAccountToken = None Bool
, containers =
[ { args = None (List Text)
, command = None (List Text)
, env =
None
( List
{ name : Text
, value : Optional Text
, valueFrom :
Optional
{ configMapKeyRef :
Optional
{ key : Text
, name : Optional Text
, optional : Optional Bool
}
, fieldRef :
Optional
{ apiVersion : Optional Text, fieldPath : Text }
, resourceFieldRef :
Optional
{ containerName : Optional Text
, divisor : Optional Text
, resource : Text
}
, secretKeyRef :
Optional
{ key : Text
, name : Optional Text
, optional : Optional Bool
}
}
}
)
, envFrom =
None
( List
{ configMapRef :
Optional
{ name : Optional Text, optional : Optional Bool }
, prefix : Optional Text
, secretRef :
Optional
{ name : Optional Text, optional : Optional Bool }
}
)
, image = Some
"index.docker.io/sourcegraph/prometheus:3.18.0@sha256:e970ed46bdf3f73477f95de9ada424ada4a24505239687ce0e474a62dac6c67b"
, imagePullPolicy = None Text
, lifecycle =
None
{ postStart :
Optional
{ exec : Optional { command : Optional (List Text) }
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
}
, preStop :
Optional
{ exec : Optional { command : Optional (List Text) }
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
}
}
, livenessProbe = Some
{ exec = None { command : Optional (List Text) }
, failureThreshold = None Natural
, httpGet = Some
{ host = None Text
, httpHeaders = None (List { name : Text, value : Text })
, path = Some "/-/healthy"
, port = < Int : Natural | String : Text >.Int 9090
, scheme = None Text
}
, initialDelaySeconds = Some 30
, periodSeconds = None Natural
, successThreshold = None Natural
, tcpSocket =
None
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds = Some 30
}
, name = "prometheus"
, ports = Some
[ { containerPort = 9090
, hostIP = None Text
, hostPort = None Natural
, name = Some "http"
, protocol = None Text
}
]
, readinessProbe = Some
{ exec = None { command : Optional (List Text) }
, failureThreshold = None Natural
, httpGet = Some
{ host = None Text
, httpHeaders = None (List { name : Text, value : Text })
, path = Some "/-/ready"
, port = < Int : Natural | String : Text >.Int 9090
, scheme = None Text
}
, initialDelaySeconds = Some 30
, periodSeconds = None Natural
, successThreshold = None Natural
, tcpSocket =
None
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds = Some 30
}
, resources = Some
{ limits = Some (toMap { memory = "3G", cpu = "2" })
, requests = Some (toMap { memory = "3G", cpu = "500m" })
}
, securityContext =
None
{ allowPrivilegeEscalation : Optional Bool
, capabilities :
Optional
{ add : Optional (List Text)
, drop : Optional (List Text)
}
, privileged : Optional Bool
, procMount : Optional Text
, readOnlyRootFilesystem : Optional Bool
, runAsGroup : Optional Natural
, runAsNonRoot : Optional Bool
, runAsUser : Optional Natural
, seLinuxOptions :
Optional
{ level : Optional Text
, role : Optional Text
, type : Optional Text
, user : Optional Text
}
, windowsOptions :
Optional
{ gmsaCredentialSpec : Optional Text
, gmsaCredentialSpecName : Optional Text
, runAsUserName : Optional Text
}
}
, startupProbe =
None
{ exec : Optional { command : Optional (List Text) }
, failureThreshold : Optional Natural
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, initialDelaySeconds : Optional Natural
, periodSeconds : Optional Natural
, successThreshold : Optional Natural
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds : Optional Natural
}
, stdin = None Bool
, stdinOnce = None Bool
, terminationMessagePath = None Text
, terminationMessagePolicy = Some "FallbackToLogsOnError"
, tty = None Bool
, volumeDevices = None (List { devicePath : Text, name : Text })
, volumeMounts = Some
[ { mountPath = "/prometheus"
, mountPropagation = None Text
, name = "data"
, readOnly = None Bool
, subPath = None Text
, subPathExpr = None Text
}
, { mountPath = "/sg_prometheus_add_ons"
, mountPropagation = None Text
, name = "config"
, readOnly = None Bool
, subPath = None Text
, subPathExpr = None Text
}
]
, workingDir = None Text
}
]
, dnsConfig =
None
{ nameservers : Optional (List Text)
, options :
Optional (List { name : Optional Text, value : Optional Text })
, searches : Optional (List Text)
}
, dnsPolicy = None Text
, enableServiceLinks = None Bool
, ephemeralContainers =
None
( List
{ args : Optional (List Text)
, command : Optional (List Text)
, env :
Optional
( List
{ name : Text
, value : Optional Text
, valueFrom :
Optional
{ configMapKeyRef :
Optional
{ key : Text
, name : Optional Text
, optional : Optional Bool
}
, fieldRef :
Optional
{ apiVersion : Optional Text
, fieldPath : Text
}
, resourceFieldRef :
Optional
{ containerName : Optional Text
, divisor : Optional Text
, resource : Text
}
, secretKeyRef :
Optional
{ key : Text
, name : Optional Text
, optional : Optional Bool
}
}
}
)
, envFrom :
Optional
( List
{ configMapRef :
Optional
{ name : Optional Text
, optional : Optional Bool
}
, prefix : Optional Text
, secretRef :
Optional
{ name : Optional Text
, optional : Optional Bool
}
}
)
, image : Optional Text
, imagePullPolicy : Optional Text
, lifecycle :
Optional
{ postStart :
Optional
{ exec : Optional { command : Optional (List Text) }
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional
(List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
}
, preStop :
Optional
{ exec : Optional { command : Optional (List Text) }
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional
(List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
}
}
, livenessProbe :
Optional
{ exec : Optional { command : Optional (List Text) }
, failureThreshold : Optional Natural
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, initialDelaySeconds : Optional Natural
, periodSeconds : Optional Natural
, successThreshold : Optional Natural
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds : Optional Natural
}
, name : Text
, ports :
Optional
( List
{ containerPort : Natural
, hostIP : Optional Text
, hostPort : Optional Natural
, name : Optional Text
, protocol : Optional Text
}
)
, readinessProbe :
Optional
{ exec : Optional { command : Optional (List Text) }
, failureThreshold : Optional Natural
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, initialDelaySeconds : Optional Natural
, periodSeconds : Optional Natural
, successThreshold : Optional Natural
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds : Optional Natural
}
, resources :
Optional
{ limits :
Optional (List { mapKey : Text, mapValue : Text })
, requests :
Optional (List { mapKey : Text, mapValue : Text })
}
, securityContext :
Optional
{ allowPrivilegeEscalation : Optional Bool
, capabilities :
Optional
{ add : Optional (List Text)
, drop : Optional (List Text)
}
, privileged : Optional Bool
, procMount : Optional Text
, readOnlyRootFilesystem : Optional Bool
, runAsGroup : Optional Natural
, runAsNonRoot : Optional Bool
, runAsUser : Optional Natural
, seLinuxOptions :
Optional
{ level : Optional Text
, role : Optional Text
, type : Optional Text
, user : Optional Text
}
, windowsOptions :
Optional
{ gmsaCredentialSpec : Optional Text
, gmsaCredentialSpecName : Optional Text
, runAsUserName : Optional Text
}
}
, startupProbe :
Optional
{ exec : Optional { command : Optional (List Text) }
, failureThreshold : Optional Natural
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, initialDelaySeconds : Optional Natural
, periodSeconds : Optional Natural
, successThreshold : Optional Natural
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds : Optional Natural
}
, stdin : Optional Bool
, stdinOnce : Optional Bool
, targetContainerName : Optional Text
, terminationMessagePath : Optional Text
, terminationMessagePolicy : Optional Text
, tty : Optional Bool
, volumeDevices :
Optional (List { devicePath : Text, name : Text })
, volumeMounts :
Optional
( List
{ mountPath : Text
, mountPropagation : Optional Text
, name : Text
, readOnly : Optional Bool
, subPath : Optional Text
, subPathExpr : Optional Text
}
)
, workingDir : Optional Text
}
)
, hostAliases =
None (List { hostnames : Optional (List Text), ip : Optional Text })
, hostIPC = None Bool
, hostNetwork = None Bool
, hostPID = None Bool
, hostname = None Text
, imagePullSecrets = None (List { name : Optional Text })
, initContainers =
None
( List
{ args : Optional (List Text)
, command : Optional (List Text)
, env :
Optional
( List
{ name : Text
, value : Optional Text
, valueFrom :
Optional
{ configMapKeyRef :
Optional
{ key : Text
, name : Optional Text
, optional : Optional Bool
}
, fieldRef :
Optional
{ apiVersion : Optional Text
, fieldPath : Text
}
, resourceFieldRef :
Optional
{ containerName : Optional Text
, divisor : Optional Text
, resource : Text
}
, secretKeyRef :
Optional
{ key : Text
, name : Optional Text
, optional : Optional Bool
}
}
}
)
, envFrom :
Optional
( List
{ configMapRef :
Optional
{ name : Optional Text
, optional : Optional Bool
}
, prefix : Optional Text
, secretRef :
Optional
{ name : Optional Text
, optional : Optional Bool
}
}
)
, image : Optional Text
, imagePullPolicy : Optional Text
, lifecycle :
Optional
{ postStart :
Optional
{ exec : Optional { command : Optional (List Text) }
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional
(List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
}
, preStop :
Optional
{ exec : Optional { command : Optional (List Text) }
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional
(List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
}
}
, livenessProbe :
Optional
{ exec : Optional { command : Optional (List Text) }
, failureThreshold : Optional Natural
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, initialDelaySeconds : Optional Natural
, periodSeconds : Optional Natural
, successThreshold : Optional Natural
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds : Optional Natural
}
, name : Text
, ports :
Optional
( List
{ containerPort : Natural
, hostIP : Optional Text
, hostPort : Optional Natural
, name : Optional Text
, protocol : Optional Text
}
)
, readinessProbe :
Optional
{ exec : Optional { command : Optional (List Text) }
, failureThreshold : Optional Natural
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, initialDelaySeconds : Optional Natural
, periodSeconds : Optional Natural
, successThreshold : Optional Natural
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds : Optional Natural
}
, resources :
Optional
{ limits :
Optional (List { mapKey : Text, mapValue : Text })
, requests :
Optional (List { mapKey : Text, mapValue : Text })
}
, securityContext :
Optional
{ allowPrivilegeEscalation : Optional Bool
, capabilities :
Optional
{ add : Optional (List Text)
, drop : Optional (List Text)
}
, privileged : Optional Bool
, procMount : Optional Text
, readOnlyRootFilesystem : Optional Bool
, runAsGroup : Optional Natural
, runAsNonRoot : Optional Bool
, runAsUser : Optional Natural
, seLinuxOptions :
Optional
{ level : Optional Text
, role : Optional Text
, type : Optional Text
, user : Optional Text
}
, windowsOptions :
Optional
{ gmsaCredentialSpec : Optional Text
, gmsaCredentialSpecName : Optional Text
, runAsUserName : Optional Text
}
}
, startupProbe :
Optional
{ exec : Optional { command : Optional (List Text) }
, failureThreshold : Optional Natural
, httpGet :
Optional
{ host : Optional Text
, httpHeaders :
Optional (List { name : Text, value : Text })
, path : Optional Text
, port : < Int : Natural | String : Text >
, scheme : Optional Text
}
, initialDelaySeconds : Optional Natural
, periodSeconds : Optional Natural
, successThreshold : Optional Natural
, tcpSocket :
Optional
{ host : Optional Text
, port : < Int : Natural | String : Text >
}
, timeoutSeconds : Optional Natural
}
, stdin : Optional Bool
, stdinOnce : Optional Bool
, terminationMessagePath : Optional Text
, terminationMessagePolicy : Optional Text
, tty : Optional Bool
, volumeDevices :
Optional (List { devicePath : Text, name : Text })
, volumeMounts :
Optional
( List
{ mountPath : Text
, mountPropagation : Optional Text
, name : Text
, readOnly : Optional Bool
, subPath : Optional Text
, subPathExpr : Optional Text
}
)
, workingDir : Optional Text
}
)
, nodeName = None Text
, nodeSelector = None (List { mapKey : Text, mapValue : Text })
, overhead = None (List { mapKey : Text, mapValue : Text })
, preemptionPolicy = None Text
, priority = None Natural
, priorityClassName = None Text
, readinessGates = None (List { conditionType : Text })
, restartPolicy = None Text
, runtimeClassName = None Text
, schedulerName = None Text
, securityContext = Some
{ fsGroup = None Natural
, fsGroupChangePolicy = None Text
, runAsGroup = None Natural
, runAsNonRoot = None Bool
, runAsUser = Some 0
, seLinuxOptions =
None
{ level : Optional Text
, role : Optional Text
, type : Optional Text
, user : Optional Text
}
, supplementalGroups = None (List Natural)
, sysctls = None (List { name : Text, value : Text })
, windowsOptions =
None
{ gmsaCredentialSpec : Optional Text
, gmsaCredentialSpecName : Optional Text
, runAsUserName : Optional Text
}
}
, serviceAccount = None Text
, serviceAccountName = Some "prometheus"
, shareProcessNamespace = None Bool
, subdomain = None Text
, terminationGracePeriodSeconds = None Natural
, tolerations =
None
( List
{ effect : Optional Text
, key : Optional Text
, operator : Optional Text
, tolerationSeconds : Optional Natural
, value : Optional Text
}
)
, topologySpreadConstraints =
None
( List
{ labelSelector :
Optional
{ matchExpressions :
Optional
( List
{ key : Text
, operator : Text
, values : Optional (List Text)
}
)
, matchLabels :
Optional (List { mapKey : Text, mapValue : Text })
}
, maxSkew : Natural
, topologyKey : Text
, whenUnsatisfiable : Text
}
)
, volumes = Some
[ { awsElasticBlockStore =
None
{ fsType : Optional Text
, partition : Optional Natural
, readOnly : Optional Bool
, volumeID : Text
}
, azureDisk =
None
{ cachingMode : Optional Text
, diskName : Text
, diskURI : Text
, fsType : Optional Text
, kind : Text
, readOnly : Optional Bool
}
, azureFile =
None
{ readOnly : Optional Bool
, secretName : Text
, shareName : Text
}
, cephfs =
None
{ monitors : List Text
, path : Optional Text
, readOnly : Optional Bool
, secretFile : Optional Text
, secretRef : Optional { name : Optional Text }
, user : Optional Text
}
, cinder =
None
{ fsType : Optional Text
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
, volumeID : Text
}
, configMap =
None
{ defaultMode : Optional Natural
, items :
Optional
( List
{ key : Text, mode : Optional Natural, path : Text }
)
, name : Optional Text
, optional : Optional Bool
}
, csi =
None
{ driver : Text
, fsType : Optional Text
, nodePublishSecretRef : Optional { name : Optional Text }
, readOnly : Optional Bool
, volumeAttributes :
Optional (List { mapKey : Text, mapValue : Text })
}
, downwardAPI =
None
{ defaultMode : Optional Natural
, items :
Optional
( List
{ fieldRef :
Optional
{ apiVersion : Optional Text, fieldPath : Text }
, mode : Optional Natural
, path : Text
, resourceFieldRef :
Optional
{ containerName : Optional Text
, divisor : Optional Text
, resource : Text
}
}
)
}
, emptyDir =
None { medium : Optional Text, sizeLimit : Optional Text }
, fc =
None
{ fsType : Optional Text
, lun : Optional Natural
, readOnly : Optional Bool
, targetWWNs : Optional (List Text)
, wwids : Optional (List Text)
}
, flexVolume =
None
{ driver : Text
, fsType : Optional Text
, options : Optional (List { mapKey : Text, mapValue : Text })
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
}
, flocker =
None { datasetName : Optional Text, datasetUUID : Optional Text }
, gcePersistentDisk =
None
{ fsType : Optional Text
, partition : Optional Natural
, pdName : Text
, readOnly : Optional Bool
}
, gitRepo =
None
{ directory : Optional Text
, repository : Text
, revision : Optional Text
}
, glusterfs =
None { endpoints : Text, path : Text, readOnly : Optional Bool }
, hostPath = None { path : Text, type : Optional Text }
, iscsi =
None
{ chapAuthDiscovery : Optional Bool
, chapAuthSession : Optional Bool
, fsType : Optional Text
, initiatorName : Optional Text
, iqn : Text
, iscsiInterface : Optional Text
, lun : Natural
, portals : Optional (List Text)
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
, targetPortal : Text
}
, name = "data"
, nfs = None { path : Text, readOnly : Optional Bool, server : Text }
, persistentVolumeClaim = Some
{ claimName = "prometheus", readOnly = None Bool }
, photonPersistentDisk = None { fsType : Optional Text, pdID : Text }
, portworxVolume =
None
{ fsType : Optional Text
, readOnly : Optional Bool
, volumeID : Text
}
, projected =
None
{ defaultMode : Optional Natural
, sources :
List
{ configMap :
Optional
{ items :
Optional
( List
{ key : Text
, mode : Optional Natural
, path : Text
}
)
, name : Optional Text
, optional : Optional Bool
}
, downwardAPI :
Optional
{ items :
Optional
( List
{ fieldRef :
Optional
{ apiVersion : Optional Text
, fieldPath : Text
}
, mode : Optional Natural
, path : Text
, resourceFieldRef :
Optional
{ containerName : Optional Text
, divisor : Optional Text
, resource : Text
}
}
)
}
, secret :
Optional
{ items :
Optional
( List
{ key : Text
, mode : Optional Natural
, path : Text
}
)
, name : Optional Text
, optional : Optional Bool
}
, serviceAccountToken :
Optional
{ audience : Optional Text
, expirationSeconds : Optional Natural
, path : Text
}
}
}
, quobyte =
None
{ group : Optional Text
, readOnly : Optional Bool
, registry : Text
, tenant : Optional Text
, user : Optional Text
, volume : Text
}
, rbd =
None
{ fsType : Optional Text
, image : Text
, keyring : Optional Text
, monitors : List Text
, pool : Optional Text
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
, user : Optional Text
}
, scaleIO =
None
{ fsType : Optional Text
, gateway : Text
, protectionDomain : Optional Text
, readOnly : Optional Bool
, secretRef : { name : Optional Text }
, sslEnabled : Optional Bool
, storageMode : Optional Text
, storagePool : Optional Text
, system : Text
, volumeName : Optional Text
}
, secret =
None
{ defaultMode : Optional Natural
, items :
Optional
( List
{ key : Text, mode : Optional Natural, path : Text }
)
, optional : Optional Bool
, secretName : Optional Text
}
, storageos =
None
{ fsType : Optional Text
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
, volumeName : Optional Text
, volumeNamespace : Optional Text
}
, vsphereVolume =
None
{ fsType : Optional Text
, storagePolicyID : Optional Text
, storagePolicyName : Optional Text
, volumePath : Text
}
}
, { awsElasticBlockStore =
None
{ fsType : Optional Text
, partition : Optional Natural
, readOnly : Optional Bool
, volumeID : Text
}
, azureDisk =
None
{ cachingMode : Optional Text
, diskName : Text
, diskURI : Text
, fsType : Optional Text
, kind : Text
, readOnly : Optional Bool
}
, azureFile =
None
{ readOnly : Optional Bool
, secretName : Text
, shareName : Text
}
, cephfs =
None
{ monitors : List Text
, path : Optional Text
, readOnly : Optional Bool
, secretFile : Optional Text
, secretRef : Optional { name : Optional Text }
, user : Optional Text
}
, cinder =
None
{ fsType : Optional Text
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
, volumeID : Text
}
, configMap = Some
{ defaultMode = Some 777
, items =
None (List { key : Text, mode : Optional Natural, path : Text })
, name = Some "prometheus"
, optional = None Bool
}
, csi =
None
{ driver : Text
, fsType : Optional Text
, nodePublishSecretRef : Optional { name : Optional Text }
, readOnly : Optional Bool
, volumeAttributes :
Optional (List { mapKey : Text, mapValue : Text })
}
, downwardAPI =
None
{ defaultMode : Optional Natural
, items :
Optional
( List
{ fieldRef :
Optional
{ apiVersion : Optional Text, fieldPath : Text }
, mode : Optional Natural
, path : Text
, resourceFieldRef :
Optional
{ containerName : Optional Text
, divisor : Optional Text
, resource : Text
}
}
)
}
, emptyDir =
None { medium : Optional Text, sizeLimit : Optional Text }
, fc =
None
{ fsType : Optional Text
, lun : Optional Natural
, readOnly : Optional Bool
, targetWWNs : Optional (List Text)
, wwids : Optional (List Text)
}
, flexVolume =
None
{ driver : Text
, fsType : Optional Text
, options : Optional (List { mapKey : Text, mapValue : Text })
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
}
, flocker =
None { datasetName : Optional Text, datasetUUID : Optional Text }
, gcePersistentDisk =
None
{ fsType : Optional Text
, partition : Optional Natural
, pdName : Text
, readOnly : Optional Bool
}
, gitRepo =
None
{ directory : Optional Text
, repository : Text
, revision : Optional Text
}
, glusterfs =
None { endpoints : Text, path : Text, readOnly : Optional Bool }
, hostPath = None { path : Text, type : Optional Text }
, iscsi =
None
{ chapAuthDiscovery : Optional Bool
, chapAuthSession : Optional Bool
, fsType : Optional Text
, initiatorName : Optional Text
, iqn : Text
, iscsiInterface : Optional Text
, lun : Natural
, portals : Optional (List Text)
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
, targetPortal : Text
}
, name = "config"
, nfs = None { path : Text, readOnly : Optional Bool, server : Text }
, persistentVolumeClaim =
None { claimName : Text, readOnly : Optional Bool }
, photonPersistentDisk = None { fsType : Optional Text, pdID : Text }
, portworxVolume =
None
{ fsType : Optional Text
, readOnly : Optional Bool
, volumeID : Text
}
, projected =
None
{ defaultMode : Optional Natural
, sources :
List
{ configMap :
Optional
{ items :
Optional
( List
{ key : Text
, mode : Optional Natural
, path : Text
}
)
, name : Optional Text
, optional : Optional Bool
}
, downwardAPI :
Optional
{ items :
Optional
( List
{ fieldRef :
Optional
{ apiVersion : Optional Text
, fieldPath : Text
}
, mode : Optional Natural
, path : Text
, resourceFieldRef :
Optional
{ containerName : Optional Text
, divisor : Optional Text
, resource : Text
}
}
)
}
, secret :
Optional
{ items :
Optional
( List
{ key : Text
, mode : Optional Natural
, path : Text
}
)
, name : Optional Text
, optional : Optional Bool
}
, serviceAccountToken :
Optional
{ audience : Optional Text
, expirationSeconds : Optional Natural
, path : Text
}
}
}
, quobyte =
None
{ group : Optional Text
, readOnly : Optional Bool
, registry : Text
, tenant : Optional Text
, user : Optional Text
, volume : Text
}
, rbd =
None
{ fsType : Optional Text
, image : Text
, keyring : Optional Text
, monitors : List Text
, pool : Optional Text
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
, user : Optional Text
}
, scaleIO =
None
{ fsType : Optional Text
, gateway : Text
, protectionDomain : Optional Text
, readOnly : Optional Bool
, secretRef : { name : Optional Text }
, sslEnabled : Optional Bool
, storageMode : Optional Text
, storagePool : Optional Text
, system : Text
, volumeName : Optional Text
}
, secret =
None
{ defaultMode : Optional Natural
, items :
Optional
( List
{ key : Text, mode : Optional Natural, path : Text }
)
, optional : Optional Bool
, secretName : Optional Text
}
, storageos =
None
{ fsType : Optional Text
, readOnly : Optional Bool
, secretRef : Optional { name : Optional Text }
, volumeName : Optional Text
, volumeNamespace : Optional Text
}
, vsphereVolume =
None
{ fsType : Optional Text
, storagePolicyID : Optional Text
, storagePolicyName : Optional Text
, volumePath : Text
}
}
]
}
}
}
, status =
None
{ availableReplicas : Optional Natural
, collisionCount : Optional Natural
, conditions :
Optional
( List
{ lastTransitionTime : Optional Text
, lastUpdateTime : Optional Text
, message : Optional Text
, reason : Optional Text
, status : Text
, type : Text
}
)
, observedGeneration : Optional Natural
, readyReplicas : Optional Natural
, replicas : Optional Natural
, unavailableReplicas : Optional Natural
, updatedReplicas : Optional Natural
}
}
Note that defaultMode
of the configMap is now 777
(natural) in the dhall output
configMap = Some
{ defaultMode = Some 777
, items =
None (List { key : Text, mode : Optional Natural, path : Text })
, name = Some "prometheus"
, optional = None Bool
}
Converting that dhall back into kubernetes yaml:
> pbpaste | dhall-to-yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
description: Collects metrics and aggregates them into graphs.
labels:
deploy: sourcegraph
sourcegraph-resource-requires: no-cluster-admin
name: prometheus
spec:
minReadySeconds: 10
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: prometheus
strategy:
type: Recreate
template:
metadata:
labels:
app: prometheus
deploy: sourcegraph
spec:
containers:
- image: "index.docker.io/sourcegraph/prometheus:3.18.0@sha256:e970ed46bdf3f73477f95de9ada424ada4a24505239687ce0e474a62dac6c67b"
livenessProbe:
httpGet:
path: /-/healthy
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
name: prometheus
ports:
- containerPort: 9090
name: http
readinessProbe:
httpGet:
path: /-/ready
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
resources:
limits:
cpu: '2'
memory: "3G"
requests:
cpu: "500m"
memory: "3G"
terminationMessagePolicy: FallbackToLogsOnError
volumeMounts:
- mountPath: /prometheus
name: data
- mountPath: /sg_prometheus_add_ons
name: config
securityContext:
runAsUser: 0
serviceAccountName: prometheus
volumes:
- name: data
persistentVolumeClaim:
claimName: prometheus
- configMap:
defaultMode: 777
name: prometheus
name: config
Note that the configMap's defaultMode has changed from 0777
(octal) in the original yaml to 777
(decimal) in the new yaml.
And indeed, trying to apply this yaml into a cluster results in an error
> kubectl apply -f test.yaml
The Deployment "prometheus" is invalid:
* spec.template.spec.volumes[1].configMap.defaultMode: Invalid value: 777: must be a number between 0 and 0777 (octal), both inclusive
Octal values are an official part of the YAML spec, and it'd be nice if Dhall supported this too (or at least had some sort of visible warning). I am not sure what the fix should be (an official octal number type, yaml-to-dhall
converting octal values to the equivalent decimal values, or something else).