local kube = import "../../../kube/kube.libsonnet"; { local radio = self, local cfg = radio.cfg, cfg:: { namespace: error "namespace must be set", appName: "radio", prefix: "", # if set, should be 'foo-' port: 2137, icecast: { location: error "location must be set", admin: error "admin must be set", limits: { clients: 100, sources: 2, threadpool: 5, queueSize: 524288, clientTimeout: 30, headerTimeout: 15, sourceTimeout: 10, burstOnConnect: true, burstSize: 65535, }, authentication: { sourcePassword: error "source password must be set", relayPassword: error "relay password must be set", adminPassword: error "admin password must be set", }, hostname: "localhost", listenPort: 8080, mounts: [], }, tag: "latest", image: "registry.k0.hswaw.net/app/radio:" + cfg.tag, resources: { requests: { cpu: "25m", memory: "50Mi", }, limits: { cpu: "100m", memory: "200Mi", }, }, }, mount:: { username: error "mount username must be defined", password: error "mount password must be defined", genre: "Classical", bitrate: 128, hidden: false, fallbackMount: null, }, makeName(suffix):: cfg.prefix + suffix, metadata:: { namespace: cfg.namespace, labels: { "app.kubernetes.io/name": cfg.appName, "app.kubernetes.io/managed-by": "kubecfg", "app.kubernetes.io/component": "radio", }, }, configMap: kube.ConfigMap(radio.makeName("icecast")) { metadata+: radio.metadata, data: { "icecast.xml": std.manifestXmlJsonml(["icecast", ["location", cfg.icecast.location], ["admin", cfg.icecast.admin], ["limits", ["clients", std.toString(cfg.icecast.limits.clients)], ["sources", std.toString(cfg.icecast.limits.sources)], ["threadpool", std.toString(cfg.icecast.limits.threadpool)], ["queue-size", std.toString(cfg.icecast.limits.queueSize)], ["client-timeout", std.toString(cfg.icecast.limits.clientTimeout)], ["header-timeout", std.toString(cfg.icecast.limits.headerTimeout)], ["source-timeout", std.toString(cfg.icecast.limits.sourceTimeout)], ["burst-on-connect", if cfg.icecast.limits.burstOnConnect then "1" else "0"], ["burst-size", std.toString(cfg.icecast.limits.burstSize)], ], ["authentication", ["source-password", cfg.icecast.authentication.sourcePassword], ["relay-user", "relay"], ["relay-password", cfg.icecast.authentication.relayPassword], ["admin-user", "admin"], ["admin-password", cfg.icecast.authentication.adminPassword], ], ["hostname", cfg.icecast.hostname], ["listen-socket", ["port", std.toString(cfg.icecast.listenPort)], ], ["fileserve", "1"], ["paths", ["webroot", "/usr/share/icecast/web"], ["adminroot", "/usr/share/icecast/admin"], ], ["logging", ["accesslog", "-"], ["errorlog", "-"], ["loglevel", "2"], ], ["security", ["chroot", "0"], ], ] + [ ["mount", {type: "normal"}, ["mount-name", m], ["username", cfg.icecast.mounts[m].username], ["password", cfg.icecast.mounts[m].password], ["public", if cfg.icecast.mounts[m].public then "1" else "0"], ["genre", cfg.icecast.mounts[m].genre], ["bitrate", std.toString(cfg.icecast.mounts[m].bitrate)], ["hidden", if cfg.icecast.mounts[m].hidden then "1" else "0"], ] + (if cfg.icecast.mounts[m].fallbackMount != null then [ ["fallback-mount", cfg.icecast.mounts[m].fallbackMount], ["fallback-override", "1"], ] else []) for m in std.objectFields(cfg.icecast.mounts) ]), }, }, deployment: kube.Deployment(radio.makeName("icecast")) { metadata+: radio.metadata, spec+: { replicas: 1, template+: { spec+: { volumes_: { config: kube.ConfigMapVolume(radio.configMap), }, containers_: { radio: kube.Container(radio.makeName("radio")) { image: cfg.image, ports_: { client: { containerPort: cfg.icecast.listenPort }, }, volumeMounts_: { config: { mountPath: "/usr/share/icecast/icecast.xml", subPath: "icecast.xml" }, }, resources: cfg.resources, }, }, }, }, }, }, svc: kube.Service(radio.makeName("icecast")) { metadata+: radio.metadata, target_pod:: radio.deployment.spec.template, spec+: { ports: [ { name: "client", port: cfg.port, targetPort: cfg.icecast.listenPort, protocol: "TCP" }, ], type: "LoadBalancer", }, }, }