From daeda9113662b75eee53969641880f2defe6ef2c Mon Sep 17 00:00:00 2001 From: Zach Bernstein Date: Sat, 7 Sep 2024 19:22:36 -0400 Subject: [PATCH] feat: add base *arr stack --- kubernetes/apps/default/kustomization.yaml | 6 +- .../default/prowlarr/app/externalsecret.yaml | 31 +++++ .../default/prowlarr/app/helmrelease.yaml | 106 +++++++++++++++ .../default/prowlarr/app/kustomization.yaml | 8 ++ kubernetes/apps/default/prowlarr/ks.yaml | 27 ++++ .../default/radarr/app/externalsecret.yaml | 35 +++++ .../apps/default/radarr/app/helmrelease.yaml | 124 ++++++++++++++++++ .../default/radarr/app/kustomization.yaml | 16 +++ .../radarr/app/resources/pushover-notify.sh | 80 +++++++++++ kubernetes/apps/default/radarr/ks.yaml | 27 ++++ .../default/sonarr/app/externalsecret.yaml | 35 +++++ .../apps/default/sonarr/app/helmrelease.yaml | 124 ++++++++++++++++++ .../default/sonarr/app/kustomization.yaml | 17 +++ .../sonarr/app/resources/pushover-notify.sh | 80 +++++++++++ .../sonarr/app/resources/refresh-series.sh | 18 +++ kubernetes/apps/default/sonarr/ks.yaml | 27 ++++ 16 files changed, 758 insertions(+), 3 deletions(-) create mode 100644 kubernetes/apps/default/prowlarr/app/externalsecret.yaml create mode 100644 kubernetes/apps/default/prowlarr/app/helmrelease.yaml create mode 100644 kubernetes/apps/default/prowlarr/app/kustomization.yaml create mode 100644 kubernetes/apps/default/prowlarr/ks.yaml create mode 100644 kubernetes/apps/default/radarr/app/externalsecret.yaml create mode 100644 kubernetes/apps/default/radarr/app/helmrelease.yaml create mode 100644 kubernetes/apps/default/radarr/app/kustomization.yaml create mode 100755 kubernetes/apps/default/radarr/app/resources/pushover-notify.sh create mode 100644 kubernetes/apps/default/radarr/ks.yaml create mode 100644 kubernetes/apps/default/sonarr/app/externalsecret.yaml create mode 100644 kubernetes/apps/default/sonarr/app/helmrelease.yaml create mode 100644 kubernetes/apps/default/sonarr/app/kustomization.yaml create mode 100755 kubernetes/apps/default/sonarr/app/resources/pushover-notify.sh create mode 100755 kubernetes/apps/default/sonarr/app/resources/refresh-series.sh create mode 100644 kubernetes/apps/default/sonarr/ks.yaml diff --git a/kubernetes/apps/default/kustomization.yaml b/kubernetes/apps/default/kustomization.yaml index 1247fe4a..f21a073f 100644 --- a/kubernetes/apps/default/kustomization.yaml +++ b/kubernetes/apps/default/kustomization.yaml @@ -20,15 +20,15 @@ resources: #- ./omegabrr/ks.yaml #- ./overseerr/ks.yaml # - ./plex/ks.yaml - #- ./prowlarr/ks.yaml + - ./prowlarr/ks.yaml #- ./qbittorrent/ks.yaml - #- ./radarr/ks.yaml + - ./radarr/ks.yaml #- ./recyclarr/ks.yaml # - ./rtlamr2mqtt/ks.yaml # - ./sabnzbd/ks.yaml # - ./slskd/ks.yaml # - ./smtp-relay/ks.yaml - #- ./sonarr/ks.yaml + - ./sonarr/ks.yaml # - ./tautulli/ks.yaml #- ./unpackerr/ks.yaml # - ./zigbee2mqtt/ks.yaml diff --git a/kubernetes/apps/default/prowlarr/app/externalsecret.yaml b/kubernetes/apps/default/prowlarr/app/externalsecret.yaml new file mode 100644 index 00000000..71d4e80e --- /dev/null +++ b/kubernetes/apps/default/prowlarr/app/externalsecret.yaml @@ -0,0 +1,31 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1beta1.json +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: prowlarr +spec: + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-connect + target: + name: prowlarr-secret + template: + engineVersion: v2 + data: + PROWLARR__AUTH__APIKEY: "{{ .PROWLARR_API_KEY }}" + PROWLARR__POSTGRES__HOST: &dbHost redspot16-rw.database.svc.cluster.local + PROWLARR__POSTGRES__PORT: "5432" + PROWLARR__POSTGRES__USER: &dbUser "{{ .PROWLARR_POSTGRES_USER }}" + PROWLARR__POSTGRES__PASSWORD: &dbPass "{{ .PROWLARR_POSTGRES_PASSWORD }}" + PROWLARR__POSTGRES__MAINDB: &dbName prowlarr + INIT_POSTGRES_DBNAME: *dbName + INIT_POSTGRES_HOST: *dbHost + INIT_POSTGRES_USER: *dbUser + INIT_POSTGRES_PASS: *dbPass + INIT_POSTGRES_SUPER_PASS: "{{ .POSTGRES_SUPER_PASS }}" + dataFrom: + - extract: + key: prowlarr + - extract: + key: cloudnative-pg diff --git a/kubernetes/apps/default/prowlarr/app/helmrelease.yaml b/kubernetes/apps/default/prowlarr/app/helmrelease.yaml new file mode 100644 index 00000000..ff4c1540 --- /dev/null +++ b/kubernetes/apps/default/prowlarr/app/helmrelease.yaml @@ -0,0 +1,106 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: prowlarr +spec: + interval: 30m + chart: + spec: + chart: app-template + version: 3.4.0 + sourceRef: + kind: HelmRepository + name: bjw-s + namespace: flux-system + install: + remediation: + retries: 3 + upgrade: + cleanupOnFail: true + remediation: + strategy: rollback + retries: 3 + values: + controllers: + prowlarr: + annotations: + reloader.stakater.com/auto: "true" + initContainers: + init-db: + image: + repository: ghcr.io/onedr0p/postgres-init + tag: 16 + envFrom: &envFrom + - secretRef: + name: prowlarr-secret + containers: + app: + image: + repository: ghcr.io/onedr0p/prowlarr-develop + tag: 1.23.1.4708@sha256:94bd657afd708efdceac0c2439e85e1c5384f5ebdbec6dd2c46169f8378cd66a + env: + PROWLARR__APP__INSTANCENAME: Prowlarr + PROWLARR__APP__THEME: dark + PROWLARR__AUTH__METHOD: External + PROWLARR__AUTH__REQUIRED: DisabledForLocalAddresses + PROWLARR__LOG__DBENABLED: "False" + PROWLARR__LOG__LEVEL: info + PROWLARR__SERVER__PORT: &port 80 + PROWLARR__UPDATE__BRANCH: develop + TZ: America/New_York + envFrom: *envFrom + probes: + liveness: &probes + enabled: true + custom: true + spec: + httpGet: + path: /ping + port: *port + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + readiness: *probes + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: { drop: ["ALL"] } + resources: + requests: + cpu: 100m + limits: + memory: 1Gi + defaultPodOptions: + securityContext: + runAsNonRoot: true + runAsUser: 568 + runAsGroup: 568 + fsGroup: 568 + fsGroupChangePolicy: OnRootMismatch + seccompProfile: { type: RuntimeDefault } + service: + app: + controller: prowlarr + ports: + http: + port: *port + ingress: + app: + annotations: + external-dns.alpha.kubernetes.io/target: internal.zebernst.dev + className: internal + hosts: + - host: "{{ .Release.Name }}.zebernst.dev" + paths: + - path: / + service: + identifier: app + port: http + persistence: + config: + type: emptyDir + tmp: + type: emptyDir diff --git a/kubernetes/apps/default/prowlarr/app/kustomization.yaml b/kubernetes/apps/default/prowlarr/app/kustomization.yaml new file mode 100644 index 00000000..83349e15 --- /dev/null +++ b/kubernetes/apps/default/prowlarr/app/kustomization.yaml @@ -0,0 +1,8 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./externalsecret.yaml + - ./helmrelease.yaml + - ../../../../templates/gatus/guarded diff --git a/kubernetes/apps/default/prowlarr/ks.yaml b/kubernetes/apps/default/prowlarr/ks.yaml new file mode 100644 index 00000000..2b478fff --- /dev/null +++ b/kubernetes/apps/default/prowlarr/ks.yaml @@ -0,0 +1,27 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &app prowlarr + namespace: flux-system +spec: + targetNamespace: default + commonMetadata: + labels: + app.kubernetes.io/name: *app + dependsOn: + - name: cloudnative-pg-cluster + - name: external-secrets-stores + path: ./kubernetes/apps/default/prowlarr/app + prune: true + sourceRef: + kind: GitRepository + name: home-kubernetes + wait: false + interval: 30m + retryInterval: 1m + timeout: 5m + postBuild: + substitute: + APP: *app diff --git a/kubernetes/apps/default/radarr/app/externalsecret.yaml b/kubernetes/apps/default/radarr/app/externalsecret.yaml new file mode 100644 index 00000000..c4577c26 --- /dev/null +++ b/kubernetes/apps/default/radarr/app/externalsecret.yaml @@ -0,0 +1,35 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1beta1.json +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: radarr +spec: + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-connect + target: + name: radarr-secret + template: + engineVersion: v2 + data: + RADARR__AUTH__APIKEY: "{{ .RADARR_API_KEY }}" + RADARR__POSTGRES__HOST: &dbHost redspot16-rw.database.svc.cluster.local + RADARR__POSTGRES__PORT: "5432" + RADARR__POSTGRES__USER: &dbUser "{{ .RADARR_POSTGRES_USER }}" + RADARR__POSTGRES__PASSWORD: &dbPass "{{ .RADARR_POSTGRES_PASSWORD }}" + RADARR__POSTGRES__MAINDB: &dbName radarr + PUSHOVER_TOKEN: "{{ .RADARR_PUSHOVER_TOKEN }}" + PUSHOVER_USER_KEY: "{{ .PUSHOVER_USER_KEY }}" + INIT_POSTGRES_DBNAME: *dbName + INIT_POSTGRES_HOST: *dbHost + INIT_POSTGRES_USER: *dbUser + INIT_POSTGRES_PASS: *dbPass + INIT_POSTGRES_SUPER_PASS: "{{ .POSTGRES_SUPER_PASS }}" + dataFrom: + - extract: + key: cloudnative-pg + - extract: + key: pushover + - extract: + key: radarr diff --git a/kubernetes/apps/default/radarr/app/helmrelease.yaml b/kubernetes/apps/default/radarr/app/helmrelease.yaml new file mode 100644 index 00000000..9731171c --- /dev/null +++ b/kubernetes/apps/default/radarr/app/helmrelease.yaml @@ -0,0 +1,124 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: radarr +spec: + interval: 30m + chart: + spec: + chart: app-template + version: 3.4.0 + sourceRef: + kind: HelmRepository + name: bjw-s + namespace: flux-system + install: + remediation: + retries: 3 + upgrade: + cleanupOnFail: true + remediation: + strategy: rollback + retries: 3 + dependsOn: + - name: synology-csi-driver + namespace: kube-system + values: + controllers: + radarr: + annotations: + reloader.stakater.com/auto: "true" + initContainers: + init-db: + image: + repository: ghcr.io/onedr0p/postgres-init + tag: 16 + envFrom: &envFrom + - secretRef: + name: radarr-secret + containers: + app: + image: + repository: ghcr.io/onedr0p/radarr-develop + tag: 5.10.1.9125@sha256:cc4aa3bbcf90671ebc85c086a1139868f613e750eb757b103ed7bdf13481c37c + env: + RADARR__APP__INSTANCENAME: Radarr + RADARR__APP__THEME: dark + RADARR__AUTH__METHOD: External + RADARR__AUTH__REQUIRED: DisabledForLocalAddresses + RADARR__LOG__DBENABLED: "False" + RADARR__LOG__LEVEL: info + RADARR__SERVER__PORT: &port 80 + RADARR__UPDATE__BRANCH: develop + TZ: America/New_York + envFrom: *envFrom + probes: + liveness: &probes + enabled: true + custom: true + spec: + httpGet: + path: /ping + port: *port + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + readiness: *probes + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: { drop: ["ALL"] } + resources: + requests: + cpu: 100m + limits: + memory: 4Gi + defaultPodOptions: + securityContext: + runAsNonRoot: true + runAsUser: 568 + runAsGroup: 568 + fsGroup: 568 + fsGroupChangePolicy: OnRootMismatch + supplementalGroups: [10000] + seccompProfile: { type: RuntimeDefault } + service: + app: + controller: radarr + ports: + http: + port: *port + ingress: + app: + annotations: + external-dns.alpha.kubernetes.io/target: internal.zebernst.dev + className: internal + hosts: + - host: "{{ .Release.Name }}.zebernst.dev" + paths: + - path: / + service: + identifier: app + port: http + persistence: + config: + type: emptyDir + scripts: + type: configMap + name: radarr-configmap + defaultMode: 0775 + globalMounts: + - path: /scripts/pushover-notify.sh + subPath: pushover-notify.sh + readOnly: true + tmp: + type: emptyDir + media: + type: nfs + server: nas.lab.home.arpa + path: /volume1/media + globalMounts: + - path: /media diff --git a/kubernetes/apps/default/radarr/app/kustomization.yaml b/kubernetes/apps/default/radarr/app/kustomization.yaml new file mode 100644 index 00000000..c1594d51 --- /dev/null +++ b/kubernetes/apps/default/radarr/app/kustomization.yaml @@ -0,0 +1,16 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./externalsecret.yaml + - ./helmrelease.yaml + - ../../../../templates/gatus/guarded +configMapGenerator: + - name: radarr-configmap + files: + - pushover-notify.sh=./resources/pushover-notify.sh +generatorOptions: + disableNameSuffixHash: true + annotations: + kustomize.toolkit.fluxcd.io/substitute: disabled diff --git a/kubernetes/apps/default/radarr/app/resources/pushover-notify.sh b/kubernetes/apps/default/radarr/app/resources/pushover-notify.sh new file mode 100755 index 00000000..30d453a5 --- /dev/null +++ b/kubernetes/apps/default/radarr/app/resources/pushover-notify.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2154 + +set -euo pipefail + +# User defined variables for pushover +PUSHOVER_USER_KEY="${PUSHOVER_USER_KEY:-required}" +PUSHOVER_TOKEN="${PUSHOVER_TOKEN:-required}" +PUSHOVER_PRIORITY="${PUSHOVER_PRIORITY:-"-2"}" + +if [[ "${radarr_eventtype:-}" == "Test" ]]; then + PUSHOVER_PRIORITY="1" + printf -v PUSHOVER_TITLE \ + "Test Notification" + printf -v PUSHOVER_MESSAGE \ + "Howdy this is a test notification from %s" \ + "${radarr_instancename:-Sonarr}" +fi + +if [[ "${radarr_eventtype:-}" == "Download" ]]; then + printf -v PUSHOVER_TITLE \ + "Movie %s" \ + "$( [[ "${radarr_isupgrade}" == "True" ]] && echo "Upgraded" || echo "Downloaded" )" + printf -v PUSHOVER_MESSAGE \ + "%s (%s)\n%s\n\nClient: %s\nQuality: %s\nSize: %s" \ + "${radarr_movie_title}" \ + "${radarr_movie_year}" \ + "${radarr_movie_overview}" \ + "${radarr_download_client:-Unknown}" \ + "${radarr_moviefile_quality:-Unknown}" \ + "$(numfmt --to iec --format "%8.2f" "${radarr_release_size:-0}")" + printf -v PUSHOVER_URL \ + "%s/movie/%s" \ + "${radarr_applicationurl:-localhost}" "${radarr_movie_tmdbid}" + printf -v PUSHOVER_URL_TITLE \ + "View movie in %s" \ + "${radarr_instancename:-Radarr}" +fi + +if [[ "${radarr_eventtype:-}" == "ManualInteractionRequired" ]]; then + PUSHOVER_PRIORITY="1" + printf -v PUSHOVER_TITLE \ + "Movie import requires intervention" + printf -v PUSHOVER_MESSAGE \ + "%s (%s)\nClient: %s" \ + "${radarr_movie_title}" \ + "${radarr_movie_year}" \ + "${radarr_download_client:-Unknown}" + printf -v PUSHOVER_URL \ + "%s/activity/queue" \ + "${radarr_applicationurl:-localhost}" + printf -v PUSHOVER_URL_TITLE \ + "View queue in %s" \ + "${radarr_instancename:-Radarr}" +fi + +json_data=$(jo \ + token="${PUSHOVER_TOKEN}" \ + user="${PUSHOVER_USER_KEY}" \ + title="${PUSHOVER_TITLE}" \ + message="${PUSHOVER_MESSAGE}" \ + url="${PUSHOVER_URL}" \ + url_title="${PUSHOVER_URL_TITLE}" \ + priority="${PUSHOVER_PRIORITY}" \ + html="1" +) + +status_code=$(curl \ + --silent \ + --write-out "%{http_code}" \ + --output /dev/null \ + --request POST \ + --header "Content-Type: application/json" \ + --data-binary "${json_data}" \ + "https://api.pushover.net/1/messages.json" \ +) + +printf "pushover notification returned with HTTP status code %s and payload: %s\n" \ + "${status_code}" \ + "$(echo "${json_data}" | jq --compact-output)" >&2 diff --git a/kubernetes/apps/default/radarr/ks.yaml b/kubernetes/apps/default/radarr/ks.yaml new file mode 100644 index 00000000..96c7c1d6 --- /dev/null +++ b/kubernetes/apps/default/radarr/ks.yaml @@ -0,0 +1,27 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &app radarr + namespace: flux-system +spec: + targetNamespace: default + commonMetadata: + labels: + app.kubernetes.io/name: *app + dependsOn: + - name: cloudnative-pg-cluster + - name: external-secrets-stores + path: ./kubernetes/apps/default/radarr/app + prune: true + sourceRef: + kind: GitRepository + name: home-kubernetes + wait: false + interval: 30m + retryInterval: 1m + timeout: 5m + postBuild: + substitute: + APP: *app diff --git a/kubernetes/apps/default/sonarr/app/externalsecret.yaml b/kubernetes/apps/default/sonarr/app/externalsecret.yaml new file mode 100644 index 00000000..87afae83 --- /dev/null +++ b/kubernetes/apps/default/sonarr/app/externalsecret.yaml @@ -0,0 +1,35 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1beta1.json +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: sonarr +spec: + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-connect + target: + name: sonarr-secret + template: + engineVersion: v2 + data: + SONARR__AUTH__APIKEY: "{{ .SONARR_API_KEY }}" + SONARR__POSTGRES__HOST: &dbHost redspot16-rw.database.svc.cluster.local + SONARR__POSTGRES__PORT: "5432" + SONARR__POSTGRES__USER: &dbUser "{{ .SONARR_POSTGRES_USER }}" + SONARR__POSTGRES__PASSWORD: &dbPass "{{ .SONARR_POSTGRES_PASSWORD }}" + SONARR__POSTGRES__MAINDB: &dbName sonarr + PUSHOVER_TOKEN: "{{ .SONARR_PUSHOVER_TOKEN }}" + PUSHOVER_USER_KEY: "{{ .PUSHOVER_USER_KEY }}" + INIT_POSTGRES_DBNAME: *dbName + INIT_POSTGRES_HOST: *dbHost + INIT_POSTGRES_USER: *dbUser + INIT_POSTGRES_PASS: *dbPass + INIT_POSTGRES_SUPER_PASS: "{{ .POSTGRES_SUPER_PASS }}" + dataFrom: + - extract: + key: sonarr + - extract: + key: cloudnative-pg + - extract: + key: pushover diff --git a/kubernetes/apps/default/sonarr/app/helmrelease.yaml b/kubernetes/apps/default/sonarr/app/helmrelease.yaml new file mode 100644 index 00000000..837e6d69 --- /dev/null +++ b/kubernetes/apps/default/sonarr/app/helmrelease.yaml @@ -0,0 +1,124 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: sonarr +spec: + interval: 30m + chart: + spec: + chart: app-template + version: 3.4.0 + sourceRef: + kind: HelmRepository + name: bjw-s + namespace: flux-system + install: + remediation: + retries: 3 + upgrade: + cleanupOnFail: true + remediation: + strategy: rollback + retries: 3 + values: + controllers: + sonarr: + annotations: + reloader.stakater.com/auto: "true" + initContainers: + init-db: + image: + repository: ghcr.io/onedr0p/postgres-init + tag: 16 + envFrom: &envFrom + - secretRef: + name: sonarr-secret + containers: + app: + image: + repository: ghcr.io/onedr0p/sonarr-develop + tag: 4.0.9.2332@sha256:2c507a6aca4612b77182ef643320a48f971e730cf6e5b6a44c23d97eb4f93961 + env: + SONARR__APP__INSTANCENAME: Sonarr + SONARR__APP__THEME: dark + SONARR__AUTH__METHOD: External + SONARR__AUTH__REQUIRED: DisabledForLocalAddresses + SONARR__LOG__DBENABLED: "False" + SONARR__LOG__LEVEL: info + SONARR__SERVER__PORT: &port 80 + SONARR__UPDATE__BRANCH: develop + TZ: America/New_York + envFrom: *envFrom + probes: + liveness: &probes + enabled: true + custom: true + spec: + httpGet: + path: /ping + port: *port + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + readiness: *probes + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: { drop: ["ALL"] } + resources: + requests: + cpu: 100m + limits: + memory: 4Gi + defaultPodOptions: + securityContext: + runAsNonRoot: true + runAsUser: 568 + runAsGroup: 568 + fsGroup: 568 + fsGroupChangePolicy: OnRootMismatch + supplementalGroups: [10000] + seccompProfile: { type: RuntimeDefault } + service: + app: + controller: sonarr + ports: + http: + port: *port + ingress: + app: + annotations: + external-dns.alpha.kubernetes.io/target: internal.zebernst.dev + className: internal + hosts: + - host: "{{ .Release.Name }}.zebernst.dev" + paths: + - path: / + service: + identifier: app + port: http + persistence: + config: + type: emptyDir + scripts: + type: configMap + name: sonarr-configmap + defaultMode: 0775 + globalMounts: + - path: /scripts/pushover-notify.sh + subPath: pushover-notify.sh + readOnly: true + - path: /scripts/refresh-series.sh + subPath: refresh-series.sh + readOnly: true + tmp: + type: emptyDir + media: + type: nfs + server: expanse.internal + path: /eros/Media + globalMounts: + - path: /media diff --git a/kubernetes/apps/default/sonarr/app/kustomization.yaml b/kubernetes/apps/default/sonarr/app/kustomization.yaml new file mode 100644 index 00000000..33c95404 --- /dev/null +++ b/kubernetes/apps/default/sonarr/app/kustomization.yaml @@ -0,0 +1,17 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./externalsecret.yaml + - ./helmrelease.yaml + - ../../../../templates/gatus/guarded +configMapGenerator: + - name: sonarr-configmap + files: + - pushover-notify.sh=./resources/pushover-notify.sh + - refresh-series.sh=./resources/refresh-series.sh +generatorOptions: + disableNameSuffixHash: true + annotations: + kustomize.toolkit.fluxcd.io/substitute: disabled diff --git a/kubernetes/apps/default/sonarr/app/resources/pushover-notify.sh b/kubernetes/apps/default/sonarr/app/resources/pushover-notify.sh new file mode 100755 index 00000000..e7c5eb44 --- /dev/null +++ b/kubernetes/apps/default/sonarr/app/resources/pushover-notify.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2154 + +set -euo pipefail + +# User defined variables for pushover +PUSHOVER_USER_KEY="${PUSHOVER_USER_KEY:-required}" +PUSHOVER_TOKEN="${PUSHOVER_TOKEN:-required}" +PUSHOVER_PRIORITY="${PUSHOVER_PRIORITY:-"-2"}" + +if [[ "${sonarr_eventtype:-}" == "Test" ]]; then + PUSHOVER_PRIORITY="1" + printf -v PUSHOVER_TITLE \ + "Test Notification" + printf -v PUSHOVER_MESSAGE \ + "Howdy this is a test notification from %s" \ + "${sonarr_instancename:-Sonarr}" +fi + +if [[ "${sonarr_eventtype:-}" == "Download" ]]; then + printf -v PUSHOVER_TITLE \ + "Episode %s" \ + "$( [[ "${sonarr_isupgrade}" == "True" ]] && echo "Upgraded" || echo "Downloaded" )" + printf -v PUSHOVER_MESSAGE \ + "%s (S%02dE%02d)\n%s\n\nQuality: %s\nClient: %s" \ + "${sonarr_series_title}" \ + "${sonarr_episodefile_seasonnumber}" \ + "${sonarr_episodefile_episodenumbers}" \ + "${sonarr_episodefile_episodetitles}" \ + "${sonarr_episodefile_quality:-Unknown}" \ + "${sonarr_download_client:-Unknown}" + printf -v PUSHOVER_URL \ + "%s/series/%s" \ + "${sonarr_applicationurl:-localhost}" \ + "${sonarr_series_titleslug}" + printf -v PUSHOVER_URL_TITLE \ + "View series in %s" \ + "${sonarr_instancename:-Sonarr}" +fi + +if [[ "${sonarr_eventtype:-}" == "ManualInteractionRequired" ]]; then + PUSHOVER_PRIORITY="1" + printf -v PUSHOVER_TITLE \ + "Episode import requires intervention" + printf -v PUSHOVER_MESSAGE \ + "%s\nClient: %s" \ + "${sonarr_series_title}" \ + "${sonarr_download_client:-Unknown}" + printf -v PUSHOVER_URL \ + "%s/activity/queue" \ + "${sonarr_applicationurl:-localhost}" + printf -v PUSHOVER_URL_TITLE \ + "View queue in %s" \ + "${sonarr_instancename:-Sonarr}" +fi + +json_data=$(jo \ + token="${PUSHOVER_TOKEN}" \ + user="${PUSHOVER_USER_KEY}" \ + title="${PUSHOVER_TITLE}" \ + message="${PUSHOVER_MESSAGE}" \ + url="${PUSHOVER_URL}" \ + url_title="${PUSHOVER_URL_TITLE}" \ + priority="${PUSHOVER_PRIORITY}" \ + html="1" +) + +status_code=$(curl \ + --silent \ + --write-out "%{http_code}" \ + --output /dev/null \ + --request POST \ + --header "Content-Type: application/json" \ + --data-binary "${json_data}" \ + "https://api.pushover.net/1/messages.json" \ +) + +printf "pushover notification returned with HTTP status code %s and payload: %s\n" \ + "${status_code}" \ + "$(echo "${json_data}" | jq --compact-output)" >&2 diff --git a/kubernetes/apps/default/sonarr/app/resources/refresh-series.sh b/kubernetes/apps/default/sonarr/app/resources/refresh-series.sh new file mode 100755 index 00000000..f88c7233 --- /dev/null +++ b/kubernetes/apps/default/sonarr/app/resources/refresh-series.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2154 + +if [[ "${sonarr_eventtype:-}" == "Grab" ]]; then + tba_count=$(curl -fsSL \ + --header "X-Api-Key: ${SONARR__AUTH__APIKEY}" \ + "http://localhost:${SONARR__SERVER__PORT}/api/v3/episode?seriesId=${sonarr_series_id}" \ + | jq --raw-output '[.[] | select((.title == "TBA") or (.title == "TBD"))] | length') + + if (( tba_count > 0 )); then + echo "INFO: Refreshing series ${sonarr_series_id} due to TBA/TBD episodes found" + curl -fsSL \ + --header "X-Api-Key: ${SONARR__AUTH__APIKEY}" \ + --header "Content-Type: application/json" \ + --data-binary '{"name": "RefreshSeries", "seriesId": '"${sonarr_series_id}"'}' \ + --request POST "http://localhost:${SONARR__SERVER__PORT}/api/v3/command" &> /dev/null + fi +fi diff --git a/kubernetes/apps/default/sonarr/ks.yaml b/kubernetes/apps/default/sonarr/ks.yaml new file mode 100644 index 00000000..c6a9922c --- /dev/null +++ b/kubernetes/apps/default/sonarr/ks.yaml @@ -0,0 +1,27 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &app sonarr + namespace: flux-system +spec: + targetNamespace: default + commonMetadata: + labels: + app.kubernetes.io/name: *app + dependsOn: + - name: cloudnative-pg-cluster + - name: external-secrets-stores + path: ./kubernetes/apps/default/sonarr/app + prune: true + sourceRef: + kind: GitRepository + name: home-kubernetes + wait: false + interval: 30m + retryInterval: 1m + timeout: 5m + postBuild: + substitute: + APP: *app