You've already forked tarr
Initial Commit
This commit is contained in:
20
cmd/autharr/LICENSE
Normal file
20
cmd/autharr/LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2024 Markus Pesch
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
37
cmd/autharr/Makefile
Normal file
37
cmd/autharr/Makefile
Normal file
@ -0,0 +1,37 @@
|
||||
VERSION?=$(shell git describe --abbrev=0)+hash.$(shell git rev-parse --short HEAD)
|
||||
|
||||
# CONTAINER_RUNTIME
|
||||
# The CONTAINER_RUNTIME variable will be used to specified the path to a
|
||||
# container runtime. This is needed to start and run a container image.
|
||||
CONTAINER_RUNTIME?=$(shell which podman)
|
||||
|
||||
# BIN
|
||||
# ==============================================================================
|
||||
autharr:
|
||||
CGO_ENABLED=0 \
|
||||
go build -ldflags "-X 'main.version=${VERSION}'" -o ${@} main.go
|
||||
|
||||
# CLEAN
|
||||
# ==============================================================================
|
||||
PHONY+=clean
|
||||
clean:
|
||||
rm --force --recursive autharr
|
||||
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
PHONY+=install
|
||||
install: autharr
|
||||
# install --directory ${DESTDIR}/etc/bash_completion.d
|
||||
# ./autharr completion bash > ${DESTDIR}/etc/bash_completion.d/autharr
|
||||
|
||||
install --directory ${DESTDIR}${PREFIX}/bin
|
||||
install --mode 0755 autharr ${DESTDIR}${PREFIX}/bin/autharr
|
||||
|
||||
install --directory ${DESTDIR}${PREFIX}/share/licenses/autharr
|
||||
install --mode 0644 LICENSE ${DESTDIR}${PREFIX}/share/licenses/autharr/LICENSE
|
||||
|
||||
# PHONY
|
||||
# ==============================================================================
|
||||
# Declare the contents of the PHONY variable as phony. We keep that information
|
||||
# in a variable so we can use it in if_changed.
|
||||
.PHONY: ${PHONY}
|
123
cmd/autharr/main.go
Normal file
123
cmd/autharr/main.go
Normal file
@ -0,0 +1,123 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"git.cryptic.systems/volker.raschek/tarr/pkg/config"
|
||||
"git.cryptic.systems/volker.raschek/tarr/pkg/domain"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var version string
|
||||
|
||||
func main() {
|
||||
rootCmd := &cobra.Command{
|
||||
Args: cobra.RangeArgs(1, 2),
|
||||
Long: `autharr reads the XML or YAML configuration file and prints the API token on stdout`,
|
||||
Example: `autharr /etc/bazarr/config.yaml
|
||||
autharr /etc/lidarr/config.xml`,
|
||||
RunE: runE,
|
||||
Version: version,
|
||||
Use: "autharr",
|
||||
}
|
||||
rootCmd.Flags().Bool("watch", false, "Listens for changes to the configuration and writes the token continuously to the output")
|
||||
|
||||
rootCmd.Execute()
|
||||
}
|
||||
|
||||
func runE(cmd *cobra.Command, args []string) error {
|
||||
watchCfg, err := cmd.Flags().GetBool("watch")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch watchCfg {
|
||||
case true:
|
||||
return runWatch(cmd, args)
|
||||
case false:
|
||||
return runSingle(cmd, args)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runSingle(_ *cobra.Command, args []string) error {
|
||||
cfg, err := config.ReadConfig(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var dest string
|
||||
if len(args) == 2 {
|
||||
dest = args[1]
|
||||
}
|
||||
|
||||
return writeConfig(cfg, dest)
|
||||
}
|
||||
|
||||
func runWatch(cmd *cobra.Command, args []string) error {
|
||||
// Initial output
|
||||
err := runSingle(cmd, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Watcher output
|
||||
configChannel, errorChannel := config.WatchConfig(cmd.Context(), args[0])
|
||||
|
||||
var dest string
|
||||
if len(args) == 2 {
|
||||
dest = args[1]
|
||||
}
|
||||
|
||||
waitFor := time.Millisecond * 100
|
||||
timer := time.NewTimer(waitFor)
|
||||
<-timer.C
|
||||
|
||||
var cachedConfig *domain.Config = nil
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-cmd.Context().Done():
|
||||
return nil
|
||||
case err := <-errorChannel:
|
||||
logrus.WithError(err).Errorln("Received from config watcher")
|
||||
case <-timer.C:
|
||||
writeConfig(cachedConfig, dest)
|
||||
case config := <-configChannel:
|
||||
cachedConfig = config
|
||||
timer.Reset(waitFor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func writeConfig(config *domain.Config, dest string) error {
|
||||
switch {
|
||||
case len(dest) <= 0:
|
||||
_, err := fmt.Fprintf(os.Stdout, "%s", config.API.Token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case len(dest) > 0:
|
||||
dirname := filepath.Dir(dest)
|
||||
|
||||
err := os.MkdirAll(dirname, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
f.WriteString(config.API.Token)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
20
cmd/healarr/LICENSE
Normal file
20
cmd/healarr/LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2024 Markus Pesch
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
37
cmd/healarr/Makefile
Normal file
37
cmd/healarr/Makefile
Normal file
@ -0,0 +1,37 @@
|
||||
VERSION?=$(shell git describe --abbrev=0)+hash.$(shell git rev-parse --short HEAD)
|
||||
|
||||
# CONTAINER_RUNTIME
|
||||
# The CONTAINER_RUNTIME variable will be used to specified the path to a
|
||||
# container runtime. This is needed to start and run a container image.
|
||||
CONTAINER_RUNTIME?=$(shell which podman)
|
||||
|
||||
# BIN
|
||||
# ==============================================================================
|
||||
healarr:
|
||||
CGO_ENABLED=0 \
|
||||
go build -ldflags "-X 'main.version=${VERSION}'" -o ${@} main.go
|
||||
|
||||
# CLEAN
|
||||
# ==============================================================================
|
||||
PHONY+=clean
|
||||
clean:
|
||||
rm --force --recursive healarr
|
||||
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
PHONY+=install
|
||||
install: healarr
|
||||
install --directory ${DESTDIR}/etc/bash_completion.d
|
||||
./healarr completion bash > ${DESTDIR}/etc/bash_completion.d/healarr
|
||||
|
||||
install --directory ${DESTDIR}${PREFIX}/bin
|
||||
install --mode 0755 healarr ${DESTDIR}${PREFIX}/bin/healarr
|
||||
|
||||
install --directory ${DESTDIR}${PREFIX}/share/licenses/healarr
|
||||
install --mode 0644 LICENSE ${DESTDIR}${PREFIX}/share/licenses/healarr/LICENSE
|
||||
|
||||
# PHONY
|
||||
# ==============================================================================
|
||||
# Declare the contents of the PHONY variable as phony. We keep that information
|
||||
# in a variable so we can use it in if_changed.
|
||||
.PHONY: ${PHONY}
|
182
cmd/healarr/main.go
Normal file
182
cmd/healarr/main.go
Normal file
@ -0,0 +1,182 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.cryptic.systems/volker.raschek/tarr/pkg/config"
|
||||
"git.cryptic.systems/volker.raschek/tarr/pkg/domain"
|
||||
"git.cryptic.systems/volker.raschek/tarr/pkg/health"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var version string
|
||||
|
||||
func main() {
|
||||
bazarrCmd := &cobra.Command{
|
||||
Args: cobra.ExactArgs(1),
|
||||
Example: `healarr bazarr https://bazarr.example.com:8443 --config /etc/bazarr/config.yaml
|
||||
healarr bazarr https://bazarr.example.com:8443 --api-token my-token`,
|
||||
RunE: runBazarrE,
|
||||
Short: "Check if a bazarr instance is healthy",
|
||||
Use: `bazarr`,
|
||||
}
|
||||
|
||||
lidarrCmd := &cobra.Command{
|
||||
Args: cobra.ExactArgs(1),
|
||||
Example: `healarr lidarr https://lidarr.example.com:8443 --config /etc/lidarr/config.xml
|
||||
healarr lidarr https://lidarr.example.com:8443 --api-token my-token`,
|
||||
RunE: runLidarrE,
|
||||
Short: "Check if a lidarr instance is healthy",
|
||||
Use: `lidarr`,
|
||||
}
|
||||
|
||||
prowlarrCmd := &cobra.Command{
|
||||
Args: cobra.ExactArgs(1),
|
||||
Example: `healarr prowlarr https://prowlarr.example.com:8443 --config /etc/prowlarr/config.xml
|
||||
healarr prowlarr https://prowlarr.example.com:8443 --api-token my-token`,
|
||||
RunE: runProwlarrE,
|
||||
Short: "Check if a prowlarr instance is healthy",
|
||||
Use: `prowlarr`,
|
||||
}
|
||||
|
||||
radarrCmd := &cobra.Command{
|
||||
Args: cobra.ExactArgs(1),
|
||||
Example: `healarr radarr https://radarr.example.com:8443 --config /etc/radarr/config.xml
|
||||
healarr radarr https://radarr.example.com:8443 --api-token my-token`,
|
||||
RunE: runRadarrE,
|
||||
Short: "Check if a radarr instance is healthy",
|
||||
Use: `radarr`,
|
||||
}
|
||||
|
||||
readarrCmd := &cobra.Command{
|
||||
Args: cobra.ExactArgs(1),
|
||||
Example: `healarr readarr https://readarr.example.com:8443 --config /etc/readarr/config.xml
|
||||
healarr readarr https://readarr.example.com:8443 --api-token my-token`,
|
||||
RunE: runReadarrrE,
|
||||
Short: "Check if a readarr instance is healthy",
|
||||
Use: `readarr`,
|
||||
}
|
||||
|
||||
sabnzbdCmd := &cobra.Command{
|
||||
Args: cobra.ExactArgs(1),
|
||||
Example: `healarr sabnzbd https://sabnzbd.example.com:8443 --config /etc/sabnzbd/config.xml
|
||||
healarr sabnzbd https://sabnzbd.example.com:8443 --api-token my-token`,
|
||||
RunE: runSabNZBdE,
|
||||
Short: "Check if a sabnzbd instance is healthy",
|
||||
Use: `sabnzbd`,
|
||||
}
|
||||
|
||||
sonarrCmd := &cobra.Command{
|
||||
Args: cobra.ExactArgs(1),
|
||||
Example: `healarr sonarr https://sonarr.example.com:8443 --config /etc/sonarr/config.xml
|
||||
healarr sonarr https://sonarr.example.com:8443 --api-token my-token`,
|
||||
RunE: runSonarr,
|
||||
Short: "Check if a sonarr instance is healthy",
|
||||
Use: `sonarr`,
|
||||
}
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Args: cobra.ExactArgs(1),
|
||||
Long: `healarr exits with a non zero exit code, when the *arr application is not healthy`,
|
||||
Version: version,
|
||||
Use: "healarr",
|
||||
}
|
||||
rootCmd.AddCommand(bazarrCmd)
|
||||
rootCmd.AddCommand(lidarrCmd)
|
||||
rootCmd.AddCommand(prowlarrCmd)
|
||||
rootCmd.AddCommand(radarrCmd)
|
||||
rootCmd.AddCommand(readarrCmd)
|
||||
rootCmd.AddCommand(sabnzbdCmd)
|
||||
rootCmd.AddCommand(sonarrCmd)
|
||||
rootCmd.PersistentFlags().String("api-token", "", "Token to access the *arr application")
|
||||
rootCmd.PersistentFlags().String("config", "", "Path to an XML or YAML config file")
|
||||
rootCmd.PersistentFlags().Bool("insecure", false, "Trust insecure TLS certificates")
|
||||
rootCmd.PersistentFlags().Duration("timeout", time.Minute, "Timeout")
|
||||
|
||||
rootCmd.Execute()
|
||||
}
|
||||
|
||||
func runBazarrE(cmd *cobra.Command, args []string) error {
|
||||
return runE(cmd, args, domain.BazarrAPIQueryKeyAPIToken)
|
||||
}
|
||||
|
||||
func runLidarrE(cmd *cobra.Command, args []string) error {
|
||||
return runE(cmd, args, domain.LidarrAPIQueryKeyAPIToken)
|
||||
}
|
||||
|
||||
func runProwlarrE(cmd *cobra.Command, args []string) error {
|
||||
return runE(cmd, args, domain.ProwlarrAPIQueryKeyAPIToken)
|
||||
}
|
||||
|
||||
func runRadarrE(cmd *cobra.Command, args []string) error {
|
||||
return runE(cmd, args, domain.RadarrAPIQueryKeyAPIToken)
|
||||
}
|
||||
|
||||
func runReadarrrE(cmd *cobra.Command, args []string) error {
|
||||
return runE(cmd, args, domain.ReadarrAPIQueryKeyAPIToken)
|
||||
}
|
||||
|
||||
func runSabNZBdE(cmd *cobra.Command, args []string) error {
|
||||
return runE(cmd, args, domain.SabNZBdAPIQueryKeyAPIToken)
|
||||
}
|
||||
|
||||
func runSonarr(cmd *cobra.Command, args []string) error {
|
||||
return runE(cmd, args, domain.SonarrAPIQueryKeyAPIToken)
|
||||
}
|
||||
|
||||
func runE(cmd *cobra.Command, args []string, queryKey string) error {
|
||||
apiToken, err := cmd.Flags().GetString("api-token")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configPath, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
insecure, err := cmd.Flags().GetBool("insecure")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
timeout, err := cmd.Flags().GetDuration("timeout")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
readinessProbeCtx, cancel := context.WithTimeout(cmd.Context(), timeout)
|
||||
defer func() { cancel() }()
|
||||
|
||||
switch {
|
||||
case len(apiToken) <= 0 && len(configPath) <= 0:
|
||||
return fmt.Errorf("At least --api-token oder --config must be defined")
|
||||
case len(apiToken) > 0 && len(configPath) <= 0:
|
||||
err = health.NewReadinessProbe(args[0]).
|
||||
QueryAdd(queryKey, apiToken).
|
||||
Insecure(insecure).
|
||||
Run(readinessProbeCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case len(apiToken) <= 0 && len(configPath) > 0:
|
||||
config, err := config.ReadConfig(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = health.NewReadinessProbe(args[0]).
|
||||
QueryAdd(queryKey, config.API.Token).
|
||||
Insecure(insecure).
|
||||
Run(readinessProbeCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("Neither --api-token nor --config can be used at the same time.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user