These can be implicitly set via secrets that follow a naming convention.pull/201/head
parent
9d085e33c2
commit
abcf4f7d8f
@ -0,0 +1,6 @@
|
||||
namespace Recyclarr.TrashLib.Config.Parsing.PostProcessing;
|
||||
|
||||
public interface IConfigPostProcessor
|
||||
{
|
||||
RootConfigYaml Process(RootConfigYaml config);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
using Recyclarr.TrashLib.Config.Secrets;
|
||||
|
||||
namespace Recyclarr.TrashLib.Config.Parsing.PostProcessing;
|
||||
|
||||
public class ImplicitUrlAndKeyPostProcessor : IConfigPostProcessor
|
||||
{
|
||||
private readonly ILogger _log;
|
||||
private readonly ISecretsProvider _secrets;
|
||||
|
||||
public ImplicitUrlAndKeyPostProcessor(ILogger log, ISecretsProvider secrets)
|
||||
{
|
||||
_log = log;
|
||||
_secrets = secrets;
|
||||
}
|
||||
|
||||
public RootConfigYaml Process(RootConfigYaml config)
|
||||
{
|
||||
return new RootConfigYaml
|
||||
{
|
||||
Radarr = ProcessService(config.Radarr),
|
||||
Sonarr = ProcessService(config.Sonarr)
|
||||
};
|
||||
}
|
||||
|
||||
private IReadOnlyDictionary<string, T>? ProcessService<T>(IReadOnlyDictionary<string, T>? services)
|
||||
where T : ServiceConfigYaml
|
||||
{
|
||||
if (services is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var updatedServices = new Dictionary<string, T>();
|
||||
foreach (var (name, service) in services)
|
||||
{
|
||||
updatedServices.Add(name, FillUrlAndKey(name, service));
|
||||
}
|
||||
|
||||
return updatedServices;
|
||||
}
|
||||
|
||||
private T FillUrlAndKey<T>(string instanceName, T config)
|
||||
where T : ServiceConfigYaml
|
||||
{
|
||||
return config with
|
||||
{
|
||||
ApiKey = config.ApiKey ?? GetSecret(instanceName, "api_key"),
|
||||
BaseUrl = config.BaseUrl ?? GetSecret(instanceName, "base_url")
|
||||
};
|
||||
}
|
||||
|
||||
private string? GetSecret(string instanceName, string property)
|
||||
{
|
||||
_log.Debug("Obtain {Property} implicitly for instance {InstanceName}", property, instanceName);
|
||||
return _secrets.Secrets.GetValueOrDefault($"{instanceName}_{property}");
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Recyclarr.TrashLib.Config.Secrets;
|
||||
|
||||
public interface ISecretsProvider
|
||||
{
|
||||
IImmutableDictionary<string, string> Secrets { get; }
|
||||
IReadOnlyDictionary<string, string> Secrets { get; }
|
||||
}
|
||||
|
@ -0,0 +1,242 @@
|
||||
using Recyclarr.TrashLib.Config.Parsing;
|
||||
using Recyclarr.TrashLib.Config.Parsing.PostProcessing;
|
||||
using Recyclarr.TrashLib.Config.Secrets;
|
||||
|
||||
namespace Recyclarr.TrashLib.Tests.Config.Parsing.PostProcessing;
|
||||
|
||||
[TestFixture]
|
||||
[Parallelizable(ParallelScope.All)]
|
||||
public class ImplicitUrlAndKeyPostProcessorTest
|
||||
{
|
||||
[Test, AutoMockData]
|
||||
public void Update_only_base_url_when_absent(
|
||||
[Frozen] ISecretsProvider secrets,
|
||||
ImplicitUrlAndKeyPostProcessor sut)
|
||||
{
|
||||
secrets.Secrets.Returns(new Dictionary<string, string>
|
||||
{
|
||||
{"instance1_base_url", "secret_base_url_1"},
|
||||
{"instance1_api_key", "secret_api_key_1"},
|
||||
{"instance2_base_url", "secret_base_url_2"},
|
||||
{"instance2_api_key", "secret_api_key_2"}
|
||||
});
|
||||
|
||||
var result = sut.Process(new RootConfigYaml
|
||||
{
|
||||
Radarr = new Dictionary<string, RadarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance1", new RadarrConfigYaml
|
||||
{
|
||||
ApiKey = "explicit_base_url"
|
||||
}
|
||||
}
|
||||
},
|
||||
Sonarr = new Dictionary<string, SonarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance2", new SonarrConfigYaml
|
||||
{
|
||||
ApiKey = "explicit_base_url"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
result.Should().BeEquivalentTo(new RootConfigYaml
|
||||
{
|
||||
Radarr = new Dictionary<string, RadarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance1", new RadarrConfigYaml
|
||||
{
|
||||
ApiKey = "explicit_base_url",
|
||||
BaseUrl = "secret_base_url_1"
|
||||
}
|
||||
}
|
||||
},
|
||||
Sonarr = new Dictionary<string, SonarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance2", new SonarrConfigYaml
|
||||
{
|
||||
ApiKey = "explicit_base_url",
|
||||
BaseUrl = "secret_base_url_2"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test, AutoMockData]
|
||||
public void Update_only_api_key_when_absent(
|
||||
[Frozen] ISecretsProvider secrets,
|
||||
ImplicitUrlAndKeyPostProcessor sut)
|
||||
{
|
||||
secrets.Secrets.Returns(new Dictionary<string, string>
|
||||
{
|
||||
{"instance1_base_url", "secret_base_url_1"},
|
||||
{"instance1_api_key", "secret_api_key_1"},
|
||||
{"instance2_base_url", "secret_base_url_2"},
|
||||
{"instance2_api_key", "secret_api_key_2"}
|
||||
});
|
||||
|
||||
var result = sut.Process(new RootConfigYaml
|
||||
{
|
||||
Radarr = new Dictionary<string, RadarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance1", new RadarrConfigYaml
|
||||
{
|
||||
BaseUrl = "explicit_base_url"
|
||||
}
|
||||
}
|
||||
},
|
||||
Sonarr = new Dictionary<string, SonarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance2", new SonarrConfigYaml
|
||||
{
|
||||
BaseUrl = "explicit_base_url"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
result.Should().BeEquivalentTo(new RootConfigYaml
|
||||
{
|
||||
Radarr = new Dictionary<string, RadarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance1", new RadarrConfigYaml
|
||||
{
|
||||
ApiKey = "secret_api_key_1",
|
||||
BaseUrl = "explicit_base_url"
|
||||
}
|
||||
}
|
||||
},
|
||||
Sonarr = new Dictionary<string, SonarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance2", new SonarrConfigYaml
|
||||
{
|
||||
ApiKey = "secret_api_key_2",
|
||||
BaseUrl = "explicit_base_url"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test, AutoMockData]
|
||||
public void Update_base_url_and_api_key_when_absent(
|
||||
[Frozen] ISecretsProvider secrets,
|
||||
ImplicitUrlAndKeyPostProcessor sut)
|
||||
{
|
||||
secrets.Secrets.Returns(new Dictionary<string, string>
|
||||
{
|
||||
{"instance1_base_url", "secret_base_url_1"},
|
||||
{"instance1_api_key", "secret_api_key_1"},
|
||||
{"instance2_base_url", "secret_base_url_2"},
|
||||
{"instance2_api_key", "secret_api_key_2"}
|
||||
});
|
||||
|
||||
var result = sut.Process(new RootConfigYaml
|
||||
{
|
||||
Radarr = new Dictionary<string, RadarrConfigYaml>
|
||||
{
|
||||
{"instance1", new RadarrConfigYaml()}
|
||||
},
|
||||
Sonarr = new Dictionary<string, SonarrConfigYaml>
|
||||
{
|
||||
{"instance2", new SonarrConfigYaml()}
|
||||
}
|
||||
});
|
||||
|
||||
result.Should().BeEquivalentTo(new RootConfigYaml
|
||||
{
|
||||
Radarr = new Dictionary<string, RadarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance1", new RadarrConfigYaml
|
||||
{
|
||||
ApiKey = "secret_api_key_1",
|
||||
BaseUrl = "secret_base_url_1"
|
||||
}
|
||||
}
|
||||
},
|
||||
Sonarr = new Dictionary<string, SonarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance2", new SonarrConfigYaml
|
||||
{
|
||||
ApiKey = "secret_api_key_2",
|
||||
BaseUrl = "secret_base_url_2"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test, AutoMockData]
|
||||
public void Change_nothing_when_all_explicitly_provided(
|
||||
[Frozen] ISecretsProvider secrets,
|
||||
ImplicitUrlAndKeyPostProcessor sut)
|
||||
{
|
||||
secrets.Secrets.Returns(new Dictionary<string, string>
|
||||
{
|
||||
{"instance1_base_url", "secret_base_url_1"},
|
||||
{"instance1_api_key", "secret_api_key_1"},
|
||||
{"instance2_base_url", "secret_base_url_2"},
|
||||
{"instance2_api_key", "secret_api_key_2"}
|
||||
});
|
||||
|
||||
var result = sut.Process(new RootConfigYaml
|
||||
{
|
||||
Radarr = new Dictionary<string, RadarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance1", new RadarrConfigYaml
|
||||
{
|
||||
BaseUrl = "explicit_base_url",
|
||||
ApiKey = "explicit_api_key"
|
||||
}
|
||||
}
|
||||
},
|
||||
Sonarr = new Dictionary<string, SonarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance2", new SonarrConfigYaml
|
||||
{
|
||||
BaseUrl = "explicit_base_url",
|
||||
ApiKey = "explicit_api_key"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
result.Should().BeEquivalentTo(new RootConfigYaml
|
||||
{
|
||||
Radarr = new Dictionary<string, RadarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance1", new RadarrConfigYaml
|
||||
{
|
||||
ApiKey = "explicit_api_key",
|
||||
BaseUrl = "explicit_base_url"
|
||||
}
|
||||
}
|
||||
},
|
||||
Sonarr = new Dictionary<string, SonarrConfigYaml>
|
||||
{
|
||||
{
|
||||
"instance2", new SonarrConfigYaml
|
||||
{
|
||||
ApiKey = "explicit_api_key",
|
||||
BaseUrl = "explicit_base_url"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in new issue