app/radio: init
diff --git a/app/radio/kube/radio.libsonnet b/app/radio/kube/radio.libsonnet
new file mode 100644
index 0000000..08a7ffb
--- /dev/null
+++ b/app/radio/kube/radio.libsonnet
@@ -0,0 +1,154 @@
+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: "100m",
+ memory: "100Mi",
+ },
+ limits: {
+ cpu: "300m",
+ memory: "200Mi",
+ },
+ },
+ },
+
+ mount:: {
+ username: error "mount username must be defined",
+ password: error "mount password must be defined",
+ genre: "Classical",
+ bitrate: 128,
+ hidden: false,
+ },
+
+ 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-password", cfg.icecast.authentication.relayPassword],
+ ["admin-password", cfg.icecast.authentication.adminPassword],
+ ],
+ ["hostname", cfg.icecast.hostname],
+ ["listen-socket",
+ ["port", std.toString(cfg.icecast.listenPort)],
+ ],
+ ["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"],
+ ]
+ 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",
+ },
+ },
+}