Repository: onedr0p/exportarr (go)

Issue:
api-key is required to not be empty
# Details

**What steps did you take and what happened:**

- Upgraded to latest exportarr v1.3.1
- Error message shown in logs:
ApiKey:
 required: api-key is required to not be empty

**What did you expect to happen:**

exportarr reads ApiKey from /config/config.xml

The following values are defined as environment variables:

        env:
          - name: URL
            value: "http://localhost"
          - name: CONFIG
            value: "/config/config.xml"
          - name: PORT
            value: "9792"
          - name: ENABLE_ADDITIONAL_METRICS
            value: "true"
          - name: ENABLE_UNKNOWN_QUEUE_ITEMS
            value: "false"

The following is my Radarr /config/config.xml:

```
<Config>
  <LogLevel>info</LogLevel>
  <UrlBase />
  <Branch>develop</Branch>
  <ApiKey>XXXXXXXXXXXX</ApiKey>
  <AuthenticationMethod>None</AuthenticationMethod>
  <InstanceName>Radarr</InstanceName>
  <PostgresUser />
  <PostgresPassword />
  <PostgresPort>5432</PostgresPort>
  <PostgresHost />
  <PostgresMainDb />
  <PostgresLogDb />
  <Port>7878</Port>
  <BindAddress>*</BindAddress>
  <LaunchBrowser>False</LaunchBrowser>
  <EnableSsl>False</EnableSsl>
  <SslPort>6969</SslPort>
  <SslCertPath />
  <SslCertPassword />
  <UpdateMechanism>Docker</UpdateMechanism>
  <AnalyticsEnabled>False</AnalyticsEnabled>
</Config>
```

**Additional Information:**


Pull request:
Fix #154: Do not require Api Key or URL in parent config, validate in…
… child config

<!--
Before you open the request please review the following guidelines and tips to help it be more easily integrated:

- Describe the scope of your change - i.e. what the change does.
- Describe any known limitations with your change.
- Please run any tests or examples that can exercise your modified code.

Thank you for contributing! We will try to test and integrate the change as soon as we can. There is no need to bump or check in on a pull request (it will clutter the discussion of the request).

Also don't be worried if the request is closed or not integrated sometimes our priorities might not match the priorities of the pull request. Don't fret, the open source community thrives on forks and GitHub makes it easy to keep your changes in a forked repo.
-->

**Description of the change**

Api Key & URL were required in the parent config, which meant that when the child Arr Config was setting API Key from the XML Config file, the parent config wasn't aware of it, and `Validate()` would fail.

This change removes the required flag from the parent config for anything that's passed down to children, trusting that the individual apps will validate the fields they need. This will be helpful in the future, for instance, if there is an App which allows access without authentication, as well.

Port & Interface are still required on the parent as these aren't things the individual collectors are aware of, they're only used for the HTTP Server.

**Benefits**

Fixes #154, clarifies that child configuration is responsible for validation.

**Possible drawbacks**

I believe ApiKey and such need to show up on the parent config to allow for them to be set before the command, (as in, `exportarr --api-key blah sabnzbd`), but this is another place where concerns aren't fully separated leading to bugs. i think when we're ready to pull in breaking changes, we should pull all of this out of the parent config, and only use the parent config for port, interface, log level, etc, which are actually universal.

**Applicable issues**

<!-- Enter any applicable Issues here (You can reference an issue using #) -->
- fixes #

**Additional information**

<!-- If there's anything else that's important and relevant to your pull request, mention that information here.-->

Fixes #154


Patch:
diff --git a/internal/config/config.go b/internal/config/config.go
index 0dcd605..2bf82ad 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -30,8 +30,8 @@ type Config struct {
 	App              string `koanf:"-"`
 	LogLevel         string `koanf:"log-level" validate:"ValidateLogLevel"`
 	LogFormat        string `koanf:"log-format" validate:"in:console,json"`
-	URL              string `koanf:"url" validate:"required|url"`
-	ApiKey           string `koanf:"api-key" validate:"required"`
+	URL              string `koanf:"url"`
+	ApiKey           string `koanf:"api-key"`
 	ApiKeyFile       string `koanf:"api-key-file"`
 	Port             int    `koanf:"port" validate:"required"`
 	Interface        string `koanf:"interface" validate:"required|ip"`


Test patch:
diff --git a/internal/arr/config/arr_integration_test.go b/internal/arr/config/arr_integration_test.go
new file mode 100644
index 0000000..6a2d1cd
--- /dev/null
+++ b/internal/arr/config/arr_integration_test.go
@@ -0,0 +1,33 @@
+package config
+
+import (
+	"testing"
+
+	base_config "github.com/onedr0p/exportarr/internal/config"
+	"github.com/spf13/pflag"
+	"github.com/stretchr/testify/require"
+)
+
+func TestArrConfigIntegration(t *testing.T) {
+	require := require.New(t)
+
+	configFlags := pflag.NewFlagSet("test", pflag.ContinueOnError)
+	base_config.RegisterConfigFlags(configFlags)
+
+	arrConfigFlags := testFlagSet()
+
+	t.Setenv("URL", "http://localhost")
+	t.Setenv("CONFIG", "test_fixtures/config.test_xml")
+	t.Setenv("PORT", "9792")
+	t.Setenv("ENABLE_ADDITIONAL_METRICS", "true")
+	t.Setenv("ENABLE_UNKNOWN_QUEUE_ITEMS", "false")
+
+	config, err := base_config.LoadConfig(configFlags)
+	require.NoError(err)
+	arrConfig, err := LoadArrConfig(*config, arrConfigFlags)
+	require.NoError(err)
+
+	require.NoError(config.Validate())
+	require.NoError(arrConfig.Validate())
+
+}
diff --git a/internal/arr/config/arr_test.go b/internal/arr/config/arr_test.go
index 8c31081..67a7a09 100644
--- a/internal/arr/config/arr_test.go
+++ b/internal/arr/config/arr_test.go
@@ -163,6 +163,23 @@ func TestLoadConfig_XMLConfig(t *testing.T) {
 	require.Equal("abcdef0123456789abcdef0123456789", config.ApiKey)
 }
 
+func TestLoadConfig_XMLConfigEnv(t *testing.T) {
+	flags := testFlagSet()
+	t.Setenv("CONFIG", "test_fixtures/config.test_xml")
+	c := base_config.Config{
+		URL: "http://localhost",
+	}
+
+	config, err := LoadArrConfig(c, flags)
+
+	require := require.New(t)
+	require.NoError(err)
+
+	// schema/host from config, port, and asdf from xml, api & version defaulted in LoadConfig.
+	require.Equal("http://localhost:7878/asdf", config.URL)
+	require.Equal("abcdef0123456789abcdef0123456789", config.ApiKey)
+}
+
 func TestValidate(t *testing.T) {
 	params := []struct {
 		name   string
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index 7a96147..451325c 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -9,14 +9,7 @@ import (
 
 func testFlagSet() *pflag.FlagSet {
 	out := pflag.NewFlagSet("test", pflag.ContinueOnError)
-	out.StringP("log-level", "l", "info", "Log level (debug, info, warn, error, fatal, panic)")
-	out.StringP("config", "c", "", "*arr config.xml file for parsing authentication information")
-	out.StringP("url", "u", "", "URL to *arr instance")
-	out.StringP("api-key", "k", "", "API Key for *arr instance")
-	out.StringP("api-key-file", "f", "", "File containing API Key for *arr instance")
-	out.Int("port", 0, "Port to listen on")
-	out.StringP("interface", "i", "", "IP address to listen on")
-	out.Bool("disable-ssl-verify", false, "Disable SSL verification")
+	RegisterConfigFlags(out)
 	return out
 }
 func TestLoadConfig_Defaults(t *testing.T) {