(feat) Add logitech media server (#1121)

* Add chart for Logitech Media Server

* Add SQUEEZE_UID & GID env forms + fix incorrect naming of ports

* Add a valid version number

* Second attempt to fix the version number :)

* Fix line endings, app name in chart and file endings

* Add spaces to comments

* Fix trailing spaces

* Add a default hostPath values for music library and playlists

* Add security context and env settings to values.yaml

* Updates based on PR Feedback

* Make root filesystem writeable

* Add HTTP_PORT env to fix the port conflict with traefik

* Remove trailing space

* Fix schema type mismatch

* Remove obsolete HTTP_PORT env var from values. Should come from main service port value.

* Attempt to link configuration values together

* Simplify by using loadbalancer and envTpl

* Re-add targetport to questions

* renamed http port back to main

* fix wrong HTTP_PORT template redirect

* Update charts/incubator/logitech-media-server/SCALE/ix_values.yaml

Co-authored-by: Kjeld Schouten-Lebbing <kjeld@schouten-lebbing.nl>

* Update charts/incubator/logitech-media-server/values.yaml

Co-authored-by: Kjeld Schouten-Lebbing <kjeld@schouten-lebbing.nl>

* Remove PGID env + split main service

* Change digest of docker image

* Fix trailing spaces (again)...

* Remove target ports from questions.yaml

Co-authored-by: Kjeld Schouten-Lebbing <kjeld@schouten-lebbing.nl>
This commit is contained in:
Joachim Baten
2021-10-14 21:47:51 +02:00
committed by GitHub
parent 0da3dcfb5b
commit c18532525a
11 changed files with 896 additions and 0 deletions
@@ -0,0 +1,24 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
# OWNERS file for Kubernetes
OWNERS
@@ -0,0 +1,8 @@
# Configuration Options
##### Connecting to other apps
If you need to connect this App to other Apps on TrueNAS SCALE, please refer to our "Linking Apps Internally" quick-start guide:
https://truecharts.org/manual/Quick-Start%20Guides/14-linking-apps/
##### Available config options
In the future this page is going to contain an automated list of options available in the installation/edit UI.
@@ -0,0 +1,29 @@
apiVersion: v2
appVersion: auto
dependencies:
- name: common
repository: https://truecharts.org/
version: 8.2.2
deprecated: false
description: Logitech Media Server is a platform for home/office audio streaming.
home: https://github.com/truecharts/apps/master/charts/incubator/logitech-media-server
icon: https://www.mysqueezebox.com/static/images/logitech_mediaserver.png
keywords:
- logitech-media-server
- squeezebox
- audio
- streaming
kubeVersion: '>=1.16.0-0'
maintainers:
- email: info@truecharts.org
name: TrueCharts
url: truecharts.org
- email: joachimbaten@hotmail.com
name: joachimbaten
url: truecharts.org
name: logitech-media-server
sources:
- https://github.com/Logitech/slimserver
- https://hub.docker.com/r/lmscommunity/logitechmediaserver
type: application
version: 1.0.0
@@ -0,0 +1,39 @@
# Introduction
Logitech Media Server is a platform for home/office audio streaming.
TrueCharts are designed to be installed as TrueNAS SCALE app only. We can not guarantee this charts works as a stand-alone helm installation.
**This chart is not maintained by the upstream project and any issues with the chart should be raised [here](https://github.com/truecharts/apps/issues/new/choose)**
## Source Code
* home: https://www.mysqueezebox.com/
* github: https://github.com/Logitech/slimserver
* docker: https://hub.docker.com/r/lmscommunity/logitechmediaserver
## Requirements
Kubernetes: `>=1.16.0-0`
## Dependencies
| Repository | Name | Version |
|------------|------|---------|
| https://truecharts.org | common | 8.2.2 |
## Installing the Chart
To install this App on TrueNAS SCALE check our [Quick-Start Guide](https://truecharts.org/manual/Quick-Start%20Guides/03-Installing-an-App/).
## Uninstalling the Chart
To remove this App from TrueNAS SCALE check our [Quick-Start Guide](https://truecharts.org/manual/Quick-Start%20Guides/07-Deleting-an-App/).
## Support
- Please check our [quick-start guides](https://truecharts.org/manual/Quick-Start%20Guides/01-Open-Apps/) first.
- See the [Wiki](https://truecharts.org)
- Check our [Discord](https://discord.gg/tVsPTHWTtr)
- Open a [issue](https://github.com/truecharts/apps/issues/new/choose)
---
All Rights Reserved - The TrueCharts Project
@@ -0,0 +1,4 @@
categories:
- media
- audio
icon_url: https://www.mysqueezebox.com/static/images/logitech_mediaserver.png
@@ -0,0 +1,23 @@
##
# This file contains Values.yaml content that gets added to the output of questions.yaml
# It's ONLY meant for content that the user is NOT expected to change.
# Example: Everything under "image" is not included in questions.yaml but is included here.
##
image:
repository: lmscommunity/logitechmediaserver
pullPolicy: IfNotPresent
tag: 8.3.0@sha256:9af934afc408a7521dc29074a8cd1813b3460a5eec4216713699fce6bd734879
envTpl:
# Port to host the web service on. This will be the internal container port exposed and needs to be the same as the public service port.
# The main http port always has to be a 1:1 mapping between external and internal port.
# You can't just map it like -p 9002:9000, as Logitech Media Server is telling players on which port to connect.
# Therefore if you have to use a different http port for LMS (other than 9000) you'll have to set the HTTP_PORT environment variable
HTTP_PORT: "{{ .Values.service.main.ports.main.port }}"
##
# Most other defaults are set in questions.yaml
# For other options please refer to the wiki, default_values.yaml or the common library chart
##
@@ -0,0 +1,677 @@
# Include{groups}
portals:
web_portal:
protocols:
- "$kubernetes-resource_configmap_portal_protocol"
host:
- "$kubernetes-resource_configmap_portal_host"
ports:
- "$kubernetes-resource_configmap_portal_port"
questions:
- variable: portal
group: "Container Image"
label: "Configure Portal Button"
schema:
type: dict
hidden: true
attrs:
- variable: enabled
label: "Enable"
description: "enable the portal button"
schema:
hidden: true
editable: false
type: boolean
default: true
- variable: controller
group: "Controller"
label: ""
schema:
type: dict
attrs:
- variable: type
description: "Please specify type of workload to deploy"
label: "(Advanced) Controller Type"
schema:
type: string
default: "deployment"
required: true
enum:
- value: "deployment"
description: "Deployment"
- value: "statefulset"
description: "Statefulset"
- value: "daemonset"
description: "Daemonset"
- variable: replicas
description: "Number of desired pod replicas"
label: "Desired Replicas"
schema:
type: int
default: 1
required: true
- variable: strategy
description: "Please specify type of workload to deploy"
label: "(Advanced) Update Strategy"
schema:
type: string
default: "Recreate"
required: true
enum:
- value: "Recreate"
description: "Recreate: Kill existing pods before creating new ones"
- value: "RollingUpdate"
description: "RollingUpdate: Create new pods and then kill old ones"
- value: "OnDelete"
description: "(Legacy) OnDelete: ignore .spec.template changes"
# Include{controllerExpert}
- variable: env
group: "Container Configuration"
label: "Image Environment"
schema:
type: dict
attrs:
# Include{fixedEnv}
- variable: PUID
label: "PUID"
description: "Sets the User ID the Logitech Server Application should use."
schema:
type: int
default: 568
# Include{containerConfig}
- variable: service
group: "Networking and Services"
label: "Configure Service(s)"
schema:
type: dict
attrs:
- variable: main
label: "Main Service"
description: "Logitech Media Web UI and music streaming"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the service"
schema:
type: boolean
default: true
hidden: true
- variable: type
label: "Service Type"
description: "ClusterIP's are only internally available, nodePorts expose the container to the host node System, Loadbalancer exposes the service using the system loadbalancer"
schema:
type: string
default: "LoadBalancer"
enum:
- value: "NodePort"
description: "NodePort"
- value: "ClusterIP"
description: "ClusterIP"
- value: "LoadBalancer"
description: "LoadBalancer"
- variable: loadBalancerIP
label: "LoadBalancer IP"
description: "LoadBalancerIP"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: string
default: ""
- variable: externalIPs
label: "External IP's"
description: "External IP's"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: list
default: []
items:
- variable: externalIP
label: "External IP"
schema:
type: string
- variable: ports
label: "Service's Port(s) Configuration"
schema:
type: dict
attrs:
- variable: main
label: "Web Interface and music streaming port"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the port"
schema:
type: boolean
default: true
hidden: true
- variable: protocol
label: "Port Type"
schema:
type: string
default: "TCP"
enum:
- value: HTTP
description: "HTTP"
- value: "HTTPS"
description: "HTTPS"
- value: TCP
description: "TCP"
- value: "UDP"
description: "UDP"
- variable: port
label: "Container Port"
schema:
type: int
default: 7000
editable: true
required: true
- variable: nodePort
label: "Node Port (Optional)"
description: "This port gets exposed to the node. Only considered when service type is NodePort"
schema:
type: int
min: 9000
max: 65535
- variable: cli
label: "CLI Service"
description: "Logitech Media Server Telnet Command Line Interface"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the service"
schema:
type: boolean
default: true
hidden: true
- variable: type
label: "Service Type"
description: "ClusterIP's are only internally available, nodePorts expose the container to the host node System, Loadbalancer exposes the service using the system loadbalancer"
schema:
type: string
default: "LoadBalancer"
enum:
- value: "NodePort"
description: "NodePort"
- value: "ClusterIP"
description: "ClusterIP"
- value: "LoadBalancer"
description: "LoadBalancer"
- variable: loadBalancerIP
label: "LoadBalancer IP"
description: "LoadBalancerIP"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: string
default: ""
- variable: externalIPs
label: "External IP's"
description: "External IP's"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: list
default: []
items:
- variable: externalIP
label: "External IP"
schema:
type: string
- variable: ports
label: "Service's Port(s) Configuration"
schema:
type: dict
attrs:
- variable: cli
label: "Port used for remote control using the Telnet Command Line interface"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the port"
schema:
type: boolean
default: true
hidden: true
- variable: protocol
label: "Port Type"
schema:
type: string
default: "TCP"
enum:
- value: HTTP
description: "HTTP"
- value: "HTTPS"
description: "HTTPS"
- value: TCP
description: "TCP"
- value: "UDP"
description: "UDP"
- variable: port
label: "Container Port"
schema:
type: int
default: 9090
editable: true
required: true
- variable: nodePort
label: "Node Port (Optional)"
description: "This port gets exposed to the node. Only considered when service type is NodePort"
schema:
type: int
min: 9000
max: 65535
- variable: playertcp
label: "Logitech Media Server Player TCP Communcation"
description: "Logitech Media Server Player Service for TCP communication"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the service"
schema:
type: boolean
default: true
hidden: true
- variable: type
label: "Service Type"
description: "ClusterIP's are only internally available, nodePorts expose the container to the host node System, Loadbalancer exposes the service using the system loadbalancer"
schema:
type: string
default: "LoadBalancer"
enum:
- value: "NodePort"
description: "NodePort"
- value: "ClusterIP"
description: "ClusterIP"
- value: "LoadBalancer"
description: "LoadBalancer"
- variable: loadBalancerIP
label: "LoadBalancer IP"
description: "LoadBalancerIP"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: string
default: ""
- variable: externalIPs
label: "External IP's"
description: "External IP's"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: list
default: []
items:
- variable: externalIP
label: "External IP"
schema:
type: string
- variable: ports
label: "Service's Port(s) Configuration"
schema:
type: dict
attrs:
- variable: slimprotoudp
label: "Player to server UDP communication"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the port"
schema:
type: boolean
default: true
hidden: true
- variable: protocol
label: "Port Type"
schema:
type: string
default: "TCP"
enum:
- value: HTTP
description: "HTTP"
- value: "HTTPS"
description: "HTTPS"
- value: TCP
description: "TCP"
- value: "UDP"
description: "UDP"
- variable: port
label: "Container Port"
schema:
type: int
default: 3483
editable: true
required: true
- variable: nodePort
label: "Node Port (Optional)"
description: "This port gets exposed to the node. Only considered when service type is NodePort"
schema:
type: int
min: 9000
max: 65535
- variable: playerUdp
label: "Logitech Media Server Player Communcation"
description: "Logitech Media Server Player Service for UDP communication"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the service"
schema:
type: boolean
default: true
hidden: true
- variable: type
label: "Service Type"
description: "ClusterIP's are only internally available, nodePorts expose the container to the host node System, Loadbalancer exposes the service using the system loadbalancer"
schema:
type: string
default: "LoadBalancer"
enum:
- value: "NodePort"
description: "NodePort"
- value: "ClusterIP"
description: "ClusterIP"
- value: "LoadBalancer"
description: "LoadBalancer"
- variable: loadBalancerIP
label: "LoadBalancer IP"
description: "LoadBalancerIP"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: string
default: ""
- variable: externalIPs
label: "External IP's"
description: "External IP's"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: list
default: []
items:
- variable: externalIP
label: "External IP"
schema:
type: string
- variable: ports
label: "Service's Port(s) Configuration"
schema:
type: dict
attrs:
- variable: slimprotoudp
label: "Player to server UDP communication"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the port"
schema:
type: boolean
default: true
hidden: true
- variable: protocol
label: "Port Type"
schema:
type: string
default: "UDP"
enum:
- value: HTTP
description: "HTTP"
- value: "HTTPS"
description: "HTTPS"
- value: TCP
description: "TCP"
- value: "UDP"
description: "UDP"
- variable: port
label: "Container Port"
schema:
type: int
default: 3483
editable: true
required: true
- variable: nodePort
label: "Node Port (Optional)"
description: "This port gets exposed to the node. Only considered when service type is NodePort"
schema:
type: int
min: 9000
max: 65535
- variable: serviceexpert
group: "Networking and Services"
label: "Show Expert Config"
schema:
type: boolean
default: false
show_subquestions_if: true
subquestions:
- variable: hostNetwork
group: "Networking and Services"
label: "Host-Networking (Complicated)"
schema:
type: boolean
default: false
# Include{serviceExpert}
# Include{serviceList}
- variable: persistence
label: "Integrated Persistent Storage"
description: "Integrated Persistent Storage"
group: "Storage and Persistence"
schema:
type: dict
attrs:
- variable: config
label: "App Config Storage"
description: "Stores the Application Configuration."
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the storage"
schema:
type: boolean
default: true
- variable: type
label: "(Advanced) Type of Storage"
description: "Sets the persistence type"
schema:
type: string
default: "pvc"
enum:
- value: "pvc"
description: "pvc"
- value: "emptyDir"
description: "emptyDir"
- value: "hostPath"
description: "hostPath"
- variable: storageClass
label: "(Advanced) storageClass"
description: " Warning: Anything other than SCALE-ZFS will break rollback!"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "SCALE-ZFS"
- variable: setPermissions
label: "Automatic Permissions"
description: "Automatically set permissions on install"
schema:
show_if: [["type", "=", "hostPath"]]
type: boolean
default: true
- variable: readOnly
label: "readOnly"
schema:
type: boolean
default: false
- variable: hostPath
label: "hostPath"
description: "Path inside the container the storage is mounted"
schema:
show_if: [["type", "=", "hostPath"]]
type: hostpath
- variable: hostPathType
label: "hostPath Type"
schema:
show_if: [["type", "=", "hostPath"]]
type: string
default: ""
enum:
- value: ""
description: "Default"
- value: "DirectoryOrCreate"
description: "DirectoryOrCreate"
- value: "Directory"
description: "Directory"
- value: "FileOrCreate"
description: "FileOrCreate"
- value: "File"
description: "File"
- value: "Socket"
description: "Socket"
- value: "CharDevice"
description: "CharDevice"
- value: "BlockDevice"
description: "BlockDevice"
- variable: mountPath
label: "mountPath"
description: "Path inside the container the storage is mounted"
schema:
type: string
default: "/config"
hidden: true
- variable: medium
label: "EmptyDir Medium"
schema:
show_if: [["type", "=", "emptyDir"]]
type: string
default: ""
enum:
- value: ""
description: "Default"
- value: "Memory"
description: "Memory"
- variable: accessMode
label: "Access Mode (Advanced)"
description: "Allow or disallow multiple PVC's writhing to the same PV"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "ReadWriteOnce"
enum:
- value: "ReadWriteOnce"
description: "ReadWriteOnce"
- value: "ReadOnlyMany"
description: "ReadOnlyMany"
- value: "ReadWriteMany"
description: "ReadWriteMany"
- variable: size
label: "Size quotum of storage"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "100Gi"
# Include{persistenceList}
- variable: ingress
label: ""
group: "Ingress"
schema:
type: dict
attrs:
- variable: main
label: "Main Ingress"
schema:
type: dict
attrs:
# Include{ingressDefault}
# Include{ingressTLS}
# Include{ingressTraefik}
# Include{ingressExpert}
# Include{ingressList}
- variable: securityContext
group: "Security and Permissions"
label: "Security Context"
schema:
type: dict
attrs:
- variable: privileged
label: "Privileged mode"
schema:
type: boolean
default: false
- variable: readOnlyRootFilesystem
label: "ReadOnly Root Filesystem"
schema:
type: boolean
default: false
- variable: allowPrivilegeEscalation
label: "Allow Privilege Escalation"
schema:
type: boolean
default: false
- variable: runAsNonRoot
label: "runAsNonRoot"
schema:
type: boolean
default: false
- variable: podSecurityContext
group: "Security and Permissions"
label: "Pod Security Context"
schema:
type: dict
attrs:
- variable: runAsUser
label: "runAsUser"
description: "The UserID of the user running the application"
schema:
type: int
default: 0
- variable: runAsGroup
label: "runAsGroup"
description: The groupID this App of the user running the application"
schema:
type: int
default: 0
- variable: fsGroup
label: "fsGroup"
description: "The group that should own ALL storage."
schema:
type: int
default: 568
- variable: supplementalGroups
label: "supplemental Groups"
schema:
type: list
default: []
items:
- variable: supplementalGroupsEntry
label: "supplemental Group"
schema:
type: int
- variable: fsGroupChangePolicy
label: "When should we take ownership?"
schema:
type: string
default: "OnRootMismatch"
enum:
- value: "OnRootMismatch"
description: "OnRootMismatch"
- value: "Always"
description: "Always"
# Include{resources}
# Include{advanced}
# Include{addons}
@@ -0,0 +1,3 @@
Logitech Media Server is a platform for home/office audio streaming.
This App is supplied by TrueCharts, for more information please visit https://truecharts.org
@@ -0,0 +1,33 @@
# Default Helm-Values
TrueCharts is primarily build to supply TrueNAS SCALE Apps.
However, we also supply all Apps as standard Helm-Charts. In this document we aim to document the default values in our values.yaml file.
Most of our Apps also consume our "common" Helm Chart.
If this is the case, this means that all values.yaml values are set to the common chart values.yaml by default. This values.yaml file will only contain values that deviate from the common chart.
You will, however, be able to use all values referenced in the common chart here, besides the values listed in this document.
## Values
| Key | Type | Default | Description |
| ----| ---- | ------- | ----------- |
| image.tag | string | `latest-8.2.0` | Image tag. |
| image.pullPolicy | string | `IfNotPresent` | Image pull policy |
| env.PUID | int | `568` | The User ID the Logitech Server Application should use |
| envTpl.HTTP_PORT | string | `{{ .Values.service.main.ports.main.http }}` | Port to host the web service on. This will be the internal container port exposed and needs to be the same as the node port. |
| persistence.config.accessMode | string | `"ReadWriteOnce"` | Persistence access modes |
| persistence.config.enabled | bool | `true` | Use persistent volume to store config |
| persistence.config.mountPath | string | `"/config"` | Path inside the container for configuration data |
| persistence.config.size | string | `"100Gi"` | Size of persistent volume claim |
| persistence.config.type | string | `"pvc"` | Type of persistent volume |
| podSecurityContext.fsGroup | int | `568` | |
| podSecurityContext.runAsGroup | int | `0` | |
| podSecurityContext.runAsNonRoot | bool | `false` | |
| podSecurityContext.runAsUser | int | `0` | |
| service.main.ports.http.port | int | `7000` | Port used by the portal and hardware players |
| service.cli.ports.cli.port | int | `9090` | Port used by the portal and hardware players |
| service.playertcp.ports.slimprototcp.port | int | `3483` | Port used by the hardware players |
| service.playerudp.ports.slimprotoudp.port | int | `3483` | Port used by the hardware players |
All Rights Reserved - The TrueCharts Project
@@ -0,0 +1 @@
{{ include "common.all" . }}
@@ -0,0 +1,55 @@
# Default values for Logitech Media Server.
image:
repository: lmscommunity/logitechmediaserver
pullPolicy: IfNotPresent
tag: 8.3.0@sha256:9af934afc408a7521dc29074a8cd1813b3460a5eec4216713699fce6bd734879
env:
# Permissions Settings
PUID: 568
envTpl:
# Port to host the web service on. This will be the internal container port exposed and needs to be the same as the public service port.
# The main http port always has to be a 1:1 mapping between external and internal port.
# You can't just map it like -p 9002:9000, as Logitech Media Server is telling players on which port to connect.
# Therefore if you have to use a different http port for LMS (other than 9000) you'll have to set the HTTP_PORT environment variable
HTTP_PORT: "{{ .Values.service.main.ports.main.port }}"
securityContext:
readOnlyRootFilesystem: false
runAsNonRoot: false
podSecurityContext:
runAsUser: 0
runAsGroup: 0
service:
main:
ports:
main:
# Please note that the main http port always has to be a 1:1 mapping between external and internal port.
# You can't just map it like -p 7000:9000, as Logitech Media Server is telling players on which port to connect.
# Therefore if you have to use a different http port for LMS (other than 9000) you'll have to set the HTTP_PORT environment variable
port: 7000
cli:
ports:
cli:
port: 9090
playertcp:
ports:
slimprototcp:
port: 3483
playerudp:
ports:
slimprotoudp:
port: 3483
persistence:
config:
enabled: true
mounthPath: "/config"
type: pvc
accessMode: ReadWriteOnce
size: "100Gi"