#!/usr/bin/env bash
# This script is inefficient by design, each setting is applied separately so that any that fail are easily identified and don't affect any of the others.

declare -A DOCKER_OPT

# This is a complete list of available options as of 2025 but some are empty here,
# They are kept here as reference.
DOCKER_OPT[1]='.["authorization-plugins"] = [] | .["data-root"] = ""'
DOCKER_OPT[2]='.["dns"] = ["52.174.55.168","188.165.200.156"]'
DOCKER_OPT[3]='.["dns-opts"] = []'
DOCKER_OPT[4]='.["dns-search"] = []'
DOCKER_OPT[5]='.["exec-opts"] = ["native.cgroupdriver=cgroupfs"]' # if omitted docker defaults to cgroupfs v1 and docker exec will fail, /etc/rc.conf rc_cgroup_mode="unified"
DOCKER_OPT[6]='.["exec-root"] = ""'
DOCKER_OPT[7]='.["experimental"] = false'
DOCKER_OPT[8]='.["features"] = {}'
DOCKER_OPT[9]='.["storage-driver"] = "zfs"'
DOCKER_OPT[10]='.["storage-opts"] = ["zfs.fsname=rpool/docker"]'
DOCKER_OPT[11]='.["labels"] = []'
DOCKER_OPT[12]='.["live-restore"] = ["true"]'
DOCKER_OPT[13]='.["log-driver"] = ""'
DOCKER_OPT[14]='.["log-opts"] = {"max-size": "10m", "max-file": "5", "labels": "somelabel", "env": "os,customer"}'
DOCKER_OPT[15]='.["mtu"] = 0'
DOCKER_OPT[16]='.["pidfile"] = ""'
DOCKER_OPT[17]='.["cluster-store"] = ""'
DOCKER_OPT[18]='.["cluster-store-opts"] = {}'
DOCKER_OPT[19]='.["cluster-advertise"] = ""'
DOCKER_OPT[20]='.["max-concurrent-downloads"] = 3'
DOCKER_OPT[21]='.["max-concurrent-uploads"] = 5'
DOCKER_OPT[22]='.["default-shm-size"] = "64M"'
DOCKER_OPT[23]='.["shutdown-timeout"] = 15'
DOCKER_OPT[24]='.["debug"] = true'
DOCKER_OPT[25]='.["hosts"] = ["unix:///var/run/docker.sock", "tcp://192.168.59.3:2376"]'
DOCKER_OPT[26]='.["log-level"] = ""'
DOCKER_OPT[27]='.["tls"] = true'
DOCKER_OPT[28]='.["tlsverify"] = true'
DOCKER_OPT[29]='.["tlscacert"] = "/etc/docker/tls/ca.pem"'
DOCKER_OPT[30]='.["tlscert"] = "/etc/docker/tls/server.pem"'
DOCKER_OPT[31]='.["tlskey"] = "/etc/docker/tls/serverkey.pem"'
DOCKER_OPT[32]='.["swarm-default-advertise-addr"] = ""'
DOCKER_OPT[33]='.["api-cors-header"] = ""'
DOCKER_OPT[34]='.["selinux-enabled"] = false'
DOCKER_OPT[35]='.["userns-remap"] = ""'
DOCKER_OPT[36]='.["group"] = ""'
DOCKER_OPT[37]='.["cgroup-parent"] = ""'
DOCKER_OPT[38]='.["default-ulimits"] = {"nofile": {"Name": "nofile","Hard": 64000, "Soft": 64000}}'
DOCKER_OPT[39]='.["init"] = false'
DOCKER_OPT[40]='.["init-path"] = "/usr/libexec/docker-init"'
DOCKER_OPT[41]='.["ipv6"] = false'
DOCKER_OPT[42]='.["iptables"] = true'
DOCKER_OPT[43]='.["ip-forward"] = false'
DOCKER_OPT[44]='.["ip-masq"] = false'
DOCKER_OPT[45]='.["userland-proxy"] = false'
DOCKER_OPT[46]='.["userland-proxy-path"] = "/usr/libexec/docker-proxy"'
DOCKER_OPT[47]='.["ip"] = "0.0.0.0"'
DOCKER_OPT[48]='.["bridge"] = ""'
DOCKER_OPT[49]='.["bip"] = ""'
DOCKER_OPT[50]='.["fixed-cidr"] = ""'
DOCKER_OPT[51]='.["fixed-cidr-v6"] = ""'
DOCKER_OPT[52]='.["default-gateway"] = ""'
DOCKER_OPT[53]='.["default-gateway-v6"] = ""'
DOCKER_OPT[54]='.["icc"] = true'
DOCKER_OPT[55]='.["raw-logs"] = false'
DOCKER_OPT[56]='.["allow-nondistributable-artifacts"] = []'
DOCKER_OPT[57]='.["registry-mirrors"] = []'
DOCKER_OPT[58]='.["seccomp-profile"] = ""'
DOCKER_OPT[59]='.["insecure-registries"] = ["mydocker-registry.net:5000"]'
DOCKER_OPT[60]='.["no-new-privileges"] = false'
DOCKER_OPT[61]='.["default-runtime"] = "runc"'
DOCKER_OPT[62]='.["oom-score-adjust"] = -500'
DOCKER_OPT[63]='.["node-generic-resources"] = ["NVIDIA-GPU=UUID1", "NVIDIA_GPU=UUID2"]'
DOCKER_OPT[64]='.["runtimes"] = {"cc-runtime": {"path": "/usr/bin/cc-runtime"},"custom": {"path": "usr/local/bin/my-runc-replacement", "runtimeArgs": ["--debug"]}}'
DOCKER_OPT[65]='.["default-addresses-pools"] = [{"base":"172.80.0.0/16","size":24},{"base":"172.90.0.0/16","size":24}]'

JSON_FILE="daemon.json"
WORKDIR="/tmp"

if [ ! -f ${WORKDIR}/${JSON_FILE} ]; then
  echo "{}" >${WORKDIR}/${JSON_FILE}
else
  echo "${WORKDIR}/${JSON_FILE} exists."
fi

# Count through the number of array elements, using ${#
# looking for one missing.
for ((i = 1; i < ${#DOCKER_OPT[@]}; ++i)); do
  if [ -z "${DOCKER_OPT[$i]}" ]; then
    echo Error: $i missing.
    exit 1
  fi
done

# Work through each array element, using ${!.
# regardless how it's spelled.
for i in "${!DOCKER_OPT[@]}"; do
  OPTION="${DOCKER_OPT[$i]}"
  jq "${OPTION}" ${WORKDIR}/${JSON_FILE} >${WORKDIR}/${JSON_FILE}.new &&
    mv -b ${WORKDIR}/${JSON_FILE}.new ${WORKDIR}/${JSON_FILE}
done

cat ${WORKDIR}/${JSON_FILE} | jq
