You've already forked tarr
							
							Compare commits
	
		
			1 Commits
		
	
	
		
			2545d55705
			...
			e7d25941fa
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						e7d25941fa
	
				 | 
					
					
						
@@ -2,7 +2,6 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@@ -27,9 +26,7 @@ autharr /etc/lidarr/config.xml`,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	rootCmd.Flags().Bool("watch", false, "Listens for changes to the configuration and writes the token continuously to the output")
 | 
						rootCmd.Flags().Bool("watch", false, "Listens for changes to the configuration and writes the token continuously to the output")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := rootCmd.Execute(); err != nil {
 | 
						rootCmd.Execute()
 | 
				
			||||||
		log.Fatalln(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func runE(cmd *cobra.Command, args []string) error {
 | 
					func runE(cmd *cobra.Command, args []string) error {
 | 
				
			||||||
@@ -87,16 +84,10 @@ func runWatch(cmd *cobra.Command, args []string) error {
 | 
				
			|||||||
		select {
 | 
							select {
 | 
				
			||||||
		case <-cmd.Context().Done():
 | 
							case <-cmd.Context().Done():
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		case err, open := <-errorChannel:
 | 
							case err := <-errorChannel:
 | 
				
			||||||
			if !open {
 | 
								logrus.WithError(err).Errorln("Received from config watcher")
 | 
				
			||||||
				return fmt.Errorf("error channel has been closed")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			logrus.WithError(err).Errorln("received from config watcher")
 | 
					 | 
				
			||||||
		case <-timer.C:
 | 
							case <-timer.C:
 | 
				
			||||||
			err = writeConfig(cachedConfig, dest)
 | 
								writeConfig(cachedConfig, dest)
 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				logrus.WithError(err).Errorln("failed to write config")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		case config := <-configChannel:
 | 
							case config := <-configChannel:
 | 
				
			||||||
			cachedConfig = config
 | 
								cachedConfig = config
 | 
				
			||||||
			timer.Reset(waitFor)
 | 
								timer.Reset(waitFor)
 | 
				
			||||||
@@ -114,23 +105,18 @@ func writeConfig(config *domain.Config, dest string) error {
 | 
				
			|||||||
	case len(dest) > 0:
 | 
						case len(dest) > 0:
 | 
				
			||||||
		dirname := filepath.Dir(dest)
 | 
							dirname := filepath.Dir(dest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// #nosec G301
 | 
					 | 
				
			||||||
		err := os.MkdirAll(dirname, 0755)
 | 
							err := os.MkdirAll(dirname, 0755)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// #nosec G304
 | 
					 | 
				
			||||||
		f, err := os.Create(dest)
 | 
							f, err := os.Create(dest)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		defer func() { _ = f.Close() }()
 | 
							defer func() { _ = f.Close() }()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_, err = f.WriteString(config.API.Token)
 | 
							f.WriteString(config.API.Token)
 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,6 @@ package main
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.cryptic.systems/volker.raschek/tarr/pkg/config"
 | 
						"git.cryptic.systems/volker.raschek/tarr/pkg/config"
 | 
				
			||||||
@@ -96,10 +95,7 @@ healarr sonarr https://sonarr.example.com:8443 --api-token my-token`,
 | 
				
			|||||||
	rootCmd.PersistentFlags().Bool("insecure", false, "Trust insecure TLS certificates")
 | 
						rootCmd.PersistentFlags().Bool("insecure", false, "Trust insecure TLS certificates")
 | 
				
			||||||
	rootCmd.PersistentFlags().Duration("timeout", time.Minute, "Timeout")
 | 
						rootCmd.PersistentFlags().Duration("timeout", time.Minute, "Timeout")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := rootCmd.Execute()
 | 
						rootCmd.Execute()
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Fatalln(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func runBazarrE(cmd *cobra.Command, args []string) error {
 | 
					func runBazarrE(cmd *cobra.Command, args []string) error {
 | 
				
			||||||
@@ -156,7 +152,7 @@ func runE(cmd *cobra.Command, args []string, queryKey string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case len(apiToken) <= 0 && len(configPath) <= 0:
 | 
						case len(apiToken) <= 0 && len(configPath) <= 0:
 | 
				
			||||||
		return fmt.Errorf("at least --api-token oder --config must be defined")
 | 
							return fmt.Errorf("At least --api-token oder --config must be defined")
 | 
				
			||||||
	case len(apiToken) > 0 && len(configPath) <= 0:
 | 
						case len(apiToken) > 0 && len(configPath) <= 0:
 | 
				
			||||||
		err = health.NewReadinessProbe(args[0]).
 | 
							err = health.NewReadinessProbe(args[0]).
 | 
				
			||||||
			QueryAdd(queryKey, apiToken).
 | 
								QueryAdd(queryKey, apiToken).
 | 
				
			||||||
@@ -179,7 +175,7 @@ func runE(cmd *cobra.Command, args []string, queryKey string) error {
 | 
				
			|||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("neither --api-token nor --config can be used at the same time")
 | 
							return fmt.Errorf("Neither --api-token nor --config can be used at the same time.")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,12 +46,11 @@ type YAMLConfig struct {
 | 
				
			|||||||
// Read reads the config struct from a file. The decoding format will be determined by the file extension like
 | 
					// Read reads the config struct from a file. The decoding format will be determined by the file extension like
 | 
				
			||||||
// `xml` or `yaml`.
 | 
					// `xml` or `yaml`.
 | 
				
			||||||
func ReadConfig(name string) (*domain.Config, error) {
 | 
					func ReadConfig(name string) (*domain.Config, error) {
 | 
				
			||||||
	// #nosec G304
 | 
					 | 
				
			||||||
	f, err := os.Open(name)
 | 
						f, err := os.Open(name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer func() { _ = f.Close() }()
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case strings.HasSuffix(name, "xml"):
 | 
						case strings.HasSuffix(name, "xml"):
 | 
				
			||||||
@@ -59,7 +58,7 @@ func ReadConfig(name string) (*domain.Config, error) {
 | 
				
			|||||||
	case strings.HasSuffix(name, "yml") || strings.HasSuffix(name, "yaml"):
 | 
						case strings.HasSuffix(name, "yml") || strings.HasSuffix(name, "yaml"):
 | 
				
			||||||
		return readYAMLConfig(f)
 | 
							return readYAMLConfig(f)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return nil, fmt.Errorf("unsupported file extension")
 | 
							return nil, fmt.Errorf("Unsupported file extension")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -98,8 +97,8 @@ func readYAMLConfig(r io.Reader) (*domain.Config, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-chan error) {
 | 
					func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-chan error) {
 | 
				
			||||||
	configChannel := make(chan *domain.Config)
 | 
						configChannel := make(chan *domain.Config, 0)
 | 
				
			||||||
	errorChannel := make(chan error)
 | 
						errorChannel := make(chan error, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		wait := time.Second * 3
 | 
							wait := time.Second * 3
 | 
				
			||||||
@@ -111,18 +110,14 @@ func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-cha
 | 
				
			|||||||
			errorChannel <- err
 | 
								errorChannel <- err
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = watcher.Add(name)
 | 
							watcher.Add(name)
 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			errorChannel <- err
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			select {
 | 
								select {
 | 
				
			||||||
			case <-ctx.Done():
 | 
								case <-ctx.Done():
 | 
				
			||||||
				close(configChannel)
 | 
									close(configChannel)
 | 
				
			||||||
				close(errorChannel)
 | 
									close(errorChannel)
 | 
				
			||||||
				return
 | 
									break
 | 
				
			||||||
			case event, open := <-watcher.Events:
 | 
								case event, open := <-watcher.Events:
 | 
				
			||||||
				if !open {
 | 
									if !open {
 | 
				
			||||||
					errorChannel <- fmt.Errorf("FSWatcher closed channel: %w", err)
 | 
										errorChannel <- fmt.Errorf("FSWatcher closed channel: %w", err)
 | 
				
			||||||
@@ -150,12 +145,11 @@ func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-cha
 | 
				
			|||||||
// WriteConfig writes the config struct into the file. The encoding format will be determined by the file extension like
 | 
					// WriteConfig writes the config struct into the file. The encoding format will be determined by the file extension like
 | 
				
			||||||
// `xml` or `yaml`.
 | 
					// `xml` or `yaml`.
 | 
				
			||||||
func WriteConfig(name string, config *domain.Config) error {
 | 
					func WriteConfig(name string, config *domain.Config) error {
 | 
				
			||||||
	// #nosec G304
 | 
					 | 
				
			||||||
	f, err := os.Create(name)
 | 
						f, err := os.Create(name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer func() { _ = f.Close() }()
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case strings.HasSuffix(name, "xml"):
 | 
						case strings.HasSuffix(name, "xml"):
 | 
				
			||||||
@@ -163,13 +157,13 @@ func WriteConfig(name string, config *domain.Config) error {
 | 
				
			|||||||
	case strings.HasSuffix(name, "yml") || strings.HasSuffix(name, "yaml"):
 | 
						case strings.HasSuffix(name, "yml") || strings.HasSuffix(name, "yaml"):
 | 
				
			||||||
		return writeYAMLConfig(f, config)
 | 
							return writeYAMLConfig(f, config)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("unsupported file extension")
 | 
							return fmt.Errorf("Unsupported file extension")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func writeXMLConfig(w io.Writer, config *domain.Config) error {
 | 
					func writeXMLConfig(w io.Writer, config *domain.Config) error {
 | 
				
			||||||
	xmlEncoder := xml.NewEncoder(w)
 | 
						xmlEncoder := xml.NewEncoder(w)
 | 
				
			||||||
	defer func() { _ = xmlEncoder.Close() }()
 | 
						defer xmlEncoder.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xmlConfig := &XMLConfig{
 | 
						xmlConfig := &XMLConfig{
 | 
				
			||||||
		APIToken: config.API.Token,
 | 
							APIToken: config.API.Token,
 | 
				
			||||||
@@ -186,7 +180,7 @@ func writeXMLConfig(w io.Writer, config *domain.Config) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func writeYAMLConfig(w io.Writer, config *domain.Config) error {
 | 
					func writeYAMLConfig(w io.Writer, config *domain.Config) error {
 | 
				
			||||||
	yamlEncoder := yaml.NewEncoder(w)
 | 
						yamlEncoder := yaml.NewEncoder(w)
 | 
				
			||||||
	defer func() { _ = yamlEncoder.Close() }()
 | 
						defer yamlEncoder.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	yamlConfig := &YAMLConfig{
 | 
						yamlConfig := &YAMLConfig{
 | 
				
			||||||
		Auth: YAMLConfigAuth{
 | 
							Auth: YAMLConfigAuth{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,6 @@ func TestReadWriteConfig_XML(t *testing.T) {
 | 
				
			|||||||
	t.Cleanup(func() { _ = os.RemoveAll(tmpDir) })
 | 
						t.Cleanup(func() { _ = os.RemoveAll(tmpDir) })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	expectedXMLConfigName := filepath.Join(tmpDir, "expected_config.xml")
 | 
						expectedXMLConfigName := filepath.Join(tmpDir, "expected_config.xml")
 | 
				
			||||||
	// #nosec G304
 | 
					 | 
				
			||||||
	f, err := os.Create(expectedXMLConfigName)
 | 
						f, err := os.Create(expectedXMLConfigName)
 | 
				
			||||||
	require.NoError(err)
 | 
						require.NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,7 +38,6 @@ func TestReadWriteConfig_XML(t *testing.T) {
 | 
				
			|||||||
	err = config.WriteConfig(actualXMLConfigName, actualConfig)
 | 
						err = config.WriteConfig(actualXMLConfigName, actualConfig)
 | 
				
			||||||
	require.NoError(err)
 | 
						require.NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// #nosec G304
 | 
					 | 
				
			||||||
	b, err := os.ReadFile(actualXMLConfigName)
 | 
						b, err := os.ReadFile(actualXMLConfigName)
 | 
				
			||||||
	require.NoError(err)
 | 
						require.NoError(err)
 | 
				
			||||||
	require.Equal(expectedXMLConfig, string(b))
 | 
						require.Equal(expectedXMLConfig, string(b))
 | 
				
			||||||
@@ -53,7 +51,6 @@ func TestReadWriteConfig_YAML(t *testing.T) {
 | 
				
			|||||||
	t.Cleanup(func() { _ = os.RemoveAll(tmpDir) })
 | 
						t.Cleanup(func() { _ = os.RemoveAll(tmpDir) })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	expectedYAMLConfigName := filepath.Join(tmpDir, "expected_config.yaml")
 | 
						expectedYAMLConfigName := filepath.Join(tmpDir, "expected_config.yaml")
 | 
				
			||||||
	// #nosec G304
 | 
					 | 
				
			||||||
	f, err := os.Create(expectedYAMLConfigName)
 | 
						f, err := os.Create(expectedYAMLConfigName)
 | 
				
			||||||
	require.NoError(err)
 | 
						require.NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -68,7 +65,6 @@ func TestReadWriteConfig_YAML(t *testing.T) {
 | 
				
			|||||||
	err = config.WriteConfig(actualYAMLConfigName, actualConfig)
 | 
						err = config.WriteConfig(actualYAMLConfigName, actualConfig)
 | 
				
			||||||
	require.NoError(err)
 | 
						require.NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// #nosec G304
 | 
					 | 
				
			||||||
	b, err := os.ReadFile(actualYAMLConfigName)
 | 
						b, err := os.ReadFile(actualYAMLConfigName)
 | 
				
			||||||
	require.NoError(err)
 | 
						require.NoError(err)
 | 
				
			||||||
	require.Equal(expectedYAMLConfig, string(b))
 | 
						require.Equal(expectedYAMLConfig, string(b))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,8 +9,8 @@ import (
 | 
				
			|||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ErrNoAPIToken error = errors.New("no API token defined")
 | 
					var ErrNoAPIToken error = errors.New("No API token defined")
 | 
				
			||||||
var ErrNoURL error = errors.New("no API token defined")
 | 
					var ErrNoURL error = errors.New("No API token defined")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ReadinessProbe struct {
 | 
					type ReadinessProbe struct {
 | 
				
			||||||
	additionalQueryValues url.Values
 | 
						additionalQueryValues url.Values
 | 
				
			||||||
@@ -40,7 +40,6 @@ func (rp *ReadinessProbe) Run(ctx context.Context) error {
 | 
				
			|||||||
	httpClient := &http.Client{
 | 
						httpClient := &http.Client{
 | 
				
			||||||
		Transport: &http.Transport{
 | 
							Transport: &http.Transport{
 | 
				
			||||||
			TLSClientConfig: &tls.Config{
 | 
								TLSClientConfig: &tls.Config{
 | 
				
			||||||
				// #nosec G402
 | 
					 | 
				
			||||||
				InsecureSkipVerify: rp.insecure,
 | 
									InsecureSkipVerify: rp.insecure,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -65,7 +64,7 @@ func (rp *ReadinessProbe) Run(ctx context.Context) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if resp.StatusCode != http.StatusOK {
 | 
						if resp.StatusCode != http.StatusOK {
 | 
				
			||||||
		return fmt.Errorf("received unexpected HTTP status code %v", resp.StatusCode)
 | 
							return fmt.Errorf("Received unexpected HTTP status code %v", resp.StatusCode)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user