I am using Jsonnet to render Kubernetes objects, I would like to use a mixin to apply multiple volume mounts to a deployment.
An example of what I've tried (k being the kausal library):
config: {
mountConfig: [
first: {
mountPath: '/path/to/first',
subPath: 'first',
data: {},
},
second: {
mountPath: '/path/to/second',
subPath: 'second',
data: {},
},
],
}
configMap: configMap.new('config')
+ configMap.withData(
{ [config.mountPath]: config.data }
for config in $.mountConfig
),
deployment: deployment.new(
name='dep1',
replicas='2',
containers=[container.new('name', 'image')]
)
+ k.util.configMapVolumeMount($.configMap, config.mountPath, config.subPath)
for mount in $.config.mountConfig
The above creates a single configmap with a key for each config file and then attempts to mount the configmap multiple times for each config file defined within the configmap.
Obviously an incomplete example, I can't figure out the syntax to do a + mixin for something in somethings
.
Afaicf subPath
handling against a single configMap
is more involved in kausal.libsonnet
libs,as k.util.configMapVolumeMount()
calls will end up adding the configmap entry to pod's volumes[]
many times.
I think that the below snippet solves your question, mind that there are also other syntax fixes (besides the implementation mechanics).
// foo.jsonnet
local k = import 'jsonnet-libs/ksonnet-util/kausal.libsonnet',
deployment = k.apps.v1.deployment,
container = k.core.v1.container,
configMap = k.core.v1.configMap,
volumeMount = k.core.v1.volumeMount;
local config = {
mountConfig: [
{
mountPath: '/path/to/first',
subPath: 'first',
data: 'Data ONE', // NOTE: must be a string
},
{
mountPath: '/path/to/second',
subPath: 'second',
data: 'Data TWO', // NOTE: must be a string
},
],
};
{
configMap:
configMap.new('config')
+ configMap.withData({
[e.subPath]: e.data
for e in config.mountConfig
}),
deployment:
local configVolName = $.configMap.metadata.name + '-volume';
deployment.new(
name='dep1',
replicas=2,
containers=[
container.new('name', 'image')
+ container.withVolumeMountsMixin([
volumeMount.new(configVolName, e.mountPath)
+ volumeMount.withSubPath(e.subPath)
for e in config.mountConfig
]),
]
)
+ deployment.spec.template.spec.withVolumesMixin([
k.core.v1.volume.fromConfigMap(configVolName, $.configMap.metadata.name),
]),
}
## Initialize jsonnet-bundler
$ jb init
## Add jsonnet libs
$ jb install https://github.com/grafana/jsonnet-libs
GET https://github.com/grafana/jsonnet-libs/archive/5f8a166911d56d0402fd52cbbce47cadfee0e466.tar.gz 200
## Add Kube 1.27 underlying libs, see https://tanka.dev/known-issues
$ jb install github.com/jsonnet-libs/k8s-libsonnet/1.27@main
GET https://github.com/jsonnet-libs/k8s-libsonnet/archive/6ecbb7709baf27f44b2e48f3529741ae6754ae6a.tar.gz 200
$ mkdir -p lib; echo "import 'github.com/jsonnet-libs/k8s-libsonnet/1.27/main.libsonnet'" > lib/k.libsonnet
## Spit-out cm+deployment JSON, need to massage it a bit for `kubectl` to slurp it in
$ jsonnet -J lib -J vendor foo.jsonnet |jq -S '.[]' |kubectl apply --dry-run=server -f-
configmap/config created (server dry run)
deployment.apps/dep1 created (server dry run)
The output from jsonnet -J lib -J vendor foo.jsonnet| yq -y .
configMap:
apiVersion: v1
data:
first: Data ONE
second: Data TWO
kind: ConfigMap
metadata:
name: config
deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep1
spec:
minReadySeconds: 10
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
name: dep1
template:
metadata:
labels:
name: dep1
spec:
containers:
- image: image
imagePullPolicy: IfNotPresent
name: name
volumeMounts:
- mountPath: /path/to/first
name: config-volume
subPath: first
- mountPath: /path/to/second
name: config-volume
subPath: second
volumes:
- configMap:
name: config
name: config-volume