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;
|
namespace Recyclarr.TrashLib.Config.Secrets;
|
||||||
|
|
||||||
public interface ISecretsProvider
|
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