public async Task Should_combine_secret_sources_in_order() { application = new Application( env => { env.ConfigurationProvider.Get <int[]>(env.SecretConfigurationSource.ScopeTo("Array")) .Should().BeEquivalentTo(new[] { 1, 2, 3 }, options => options.WithStrictOrdering()); env.ConfigurationProvider.Get <int[]>(env.ConfigurationSource.ScopeTo("Array")) .Should().BeEmpty(); }); host = new VostokHost(new TestHostSettings(application, setup => { SetupEnvironment(setup); setup.SetupConfiguration(c => c.AddSecretSource(new ObjectSource(new { Array = new[] { 1 } }))); setup.SetupConfiguration(c => c.AddSecretSource(new ObjectSource(new { Array = new[] { 2 } }))); setup.SetupConfiguration(c => c.CustomizeSecretConfigurationSource(s => s.CombineWith(new ObjectSource(new { Array = new[] { 3 } }), new SettingsMergeOptions { ArrayMergeStyle = ArrayMergeStyle.Concat }))); setup.SetupConfiguration(c => c.CustomizeSecretSettingsMerging(s => s.ArrayMergeStyle = ArrayMergeStyle.Concat)); setup.SetupConfiguration(c => c.GetIntermediateSecretConfiguration <int[]>("Array") .Should().BeEquivalentTo(new[] { 1, 2, 3 }, options => options.WithStrictOrdering())); setup.SetupConfiguration(c => c.CustomizeConfigurationContext(env => env.ConfigurationProvider.Get <int[]>(env.SecretConfigurationSource.ScopeTo("Array")) .Should().BeEquivalentTo(new[] { 1, 2, 3 }, options => options.WithStrictOrdering()))); })); var result = await host.RunAsync(); result.State.Should().Be(VostokApplicationState.Exited); }
public void Start_should_check_that_beacon_has_started() { var zkClient = Substitute.For <IZooKeeperClient>(); zkClient.CreateAsync(Arg.Any <CreateRequest>()).Returns(Task.FromResult(CreateResult.Unsuccessful(ZooKeeperStatus.AuthFailed, "", null))); application = new PortRequiresApplication(); host = new VostokHost( new TestHostSettings( application, s => { SetupEnvironment(s); s.SetupZooKeeperClient(zkSetup => zkSetup.UseInstance(zkClient)); s.SetupServiceBeacon( beaconSetup => beaconSetup.SetupReplicaInfo( replicaInfoSetup => { replicaInfoSetup.SetApplication("auth-test"); })); }) { BeaconRegistrationWaitEnabled = true, BeaconRegistrationTimeout = 2.Seconds() }); Action checkStart = () => host.Start(); checkStart.Should().Throw <Exception>().Where(e => e.Message.Contains("beacon hasn't registered")); host.ApplicationState.Should().Be(VostokApplicationState.CrashedDuringInitialization); }
public async Task Should_allow_to_use_datacenters_during_clusterconfig_setup() { application = new Application(); host = new VostokHost(new TestHostSettings(application, builder => { builder.SetupApplicationIdentity( id => id .SetProject("infra") .SetSubproject("vostok") .SetApplication("app") .SetInstance("1")); builder.SetupApplicationIdentity((id, ctx) => id.SetEnvironment("env")); builder.SetupLog(b => b.SetupConsoleLog()); builder.SetupConfiguration( (config, context) => { context.Datacenters.GetLocalDatacenter().Should().BeNull(); }); })); var result = await host.RunAsync(); result.State.Should().Be(VostokApplicationState.Exited); }
private static void CheckConfigurationTypes(IVostokApplication application, IVostokHostingEnvironment environment, List <string> errors) => CheckConfigurationTypesInternal( () => RequirementDetector.GetRequiredConfigurations(application), () => RequirementDetector.GetRequiredSecretConfigurations(application), () => RequirementDetector.GetRequiredMergedConfigurations(application), environment, errors);
/// <summary> /// Initializes given <paramref name="application"/> and then runs it. /// </summary> public static void InitializeAndRun( [NotNull] this IVostokApplication application, [NotNull] IVostokHostingEnvironment environment) { application.Initialize(environment); application.Run(environment); }
public static void EnsureConfigurations([NotNull] IVostokApplication application, [NotNull] IVostokHostingEnvironmentBuilder builder) { void SetupSource(IConfigurationProvider provider, IConfigurationSource source, string[] scope, Type type) { if (scope.Any()) { source = source.ScopeTo(scope); } provider.SetupSourceFor(source, type); } builder.SetupConfiguration( b => b.CustomizeConfigurationContext( context => { foreach (var requirement in RequirementDetector.GetRequiredConfigurations(application)) { SetupSource(context.ConfigurationProvider, context.ConfigurationSource, requirement.Scope, requirement.Type); } foreach (var requirement in RequirementDetector.GetRequiredSecretConfigurations(application)) { SetupSource(context.SecretConfigurationProvider, context.SecretConfigurationSource, requirement.Scope, requirement.Type); } foreach (var requirement in RequirementDetector.GetRequiredMergedConfigurations(application)) { SetupSource(context.ConfigurationProvider, context.MergedConfigurationSource, requirement.Scope, requirement.Type); } })); }
public static void EnsurePort([NotNull] IVostokApplication application, [NotNull] IVostokHostingEnvironmentBuilder builder) { if (RequirementDetector.RequiresPort(application)) { builder.SetPort(FreeTcpPortFinder.GetFreePort()); } }
public async Task Should_allow_to_use_configuration_during_configuration_setup() { application = new Application(); host = new VostokHost(new TestHostSettings(application, builder => { builder.SetupApplicationIdentity( id => id .SetProject("infra") .SetSubproject("vostok") .SetApplication("app") .SetInstance("1")); builder.SetupApplicationIdentity((id, ctx) => id.SetEnvironment("env")); builder.SetupConfiguration( config => { config.AddSource(new ObjectSource(new { A = "hello" })); }); builder.SetupConfiguration( config => config.GetIntermediateConfiguration <ApplicationSettings>().A.Should().Be("hello")); })); var result = await host.RunAsync(); result.State.Should().Be(VostokApplicationState.Exited); }
/// <summary> /// Checks whether given <paramref name="environment"/> satisfies all requirements imposed by <paramref name="application"/>. /// </summary> /// <exception cref="RequirementsCheckException">Some of application's requirements were not satisfied.</exception> public static void Check( [NotNull] IVostokApplication application, [NotNull] IVostokHostingEnvironment environment) { if (!TryCheck(application, environment, out var errors)) { throw new RequirementsCheckException(application.GetType(), errors); } }
public void Start_should_wait_until_given_state_occurs(VostokApplicationState stateToAwait) { application = new Application(); host = new VostokHost(new TestHostSettings(application, SetupEnvironment)); host.Start(stateToAwait); host.ApplicationState.Should().Match <VostokApplicationState>(state => state >= stateToAwait); host.Stop(); host.ApplicationState.IsTerminal().Should().BeTrue(); }
private static IEnumerable <Type> GetApplicationTypes(IVostokApplication application) { yield return(application.GetType()); if (application is CompositeApplication compositeApplication) { foreach (var type in compositeApplication.ApplicationTypes) { yield return(type); } } }
public void Start_should_not_throw_on_run_fail() { application = new BadApplication(false); host = new VostokHost(new TestHostSettings(application, SetupEnvironment)); Action checkStart = () => host.Start(VostokApplicationState.Initialized); checkStart.Should().NotThrow(); Action checkStop = () => host.Stop(); checkStop.Should().Throw <Exception>().WithMessage("run"); }
public async Task Should_allow_to_setup_sources_in_an_idempotent_way() { application = new Application( env => { env.ConfigurationProvider.SetupSourceFor <ApplicationSettings>(env.ConfigurationSource); env.SecretConfigurationProvider.SetupSourceFor <ApplicationSecretSettings>(env.SecretConfigurationSource); }); host = new VostokHost(new TestHostSettings(application, SetupEnvironment)); var result = await host.RunAsync(); result.State.Should().Be(VostokApplicationState.Exited); }
public void TestSetup() { application = new Application(); hostExtensions = new TestHostExtensions(); environment = Substitute.For <IVostokHostingEnvironment>(); environment.HostExtensions.Returns(_ => hostExtensions); environment.ConfigurationProvider.Returns(configProvider = Substitute.For <IConfigurationProvider>()); environment.SecretConfigurationProvider.Returns(secretConfigProvider = Substitute.For <IConfigurationProvider>()); environment.Port.Returns(123); hostExtensions.Add(Guid.Empty); hostExtensions.Add("key", Guid.Empty); configProvider.Get <string>().Returns(string.Empty); secretConfigProvider.Get <string>().Returns(string.Empty); }
public async Task Should_allow_to_use_statically_configured_app_identity_properties_during_configuration_setup() { application = new Application(); host = new VostokHost(new TestHostSettings(application, builder => { builder.SetupApplicationIdentity( id => id .SetProject("infra") .SetSubproject("vostok") .SetApplication("app") .SetInstance("1")); builder.SetupApplicationIdentity((id, ctx) => id.SetEnvironment("env")); builder.SetupLog(log => log.SetupConsoleLog()); builder.SetupConfiguration( (config, ctx) => { ctx.Log.Info(ctx.ApplicationIdentity.ToString()); ctx.ApplicationIdentity.Project.Should().Be("infra"); ctx.ApplicationIdentity.Subproject.Should().Be("vostok"); ctx.ApplicationIdentity.Application.Should().Be("app"); ctx.ApplicationIdentity.Instance.Should().Be("1"); // ReSharper disable once ReturnValueOfPureMethodIsNotUsed Action action = () => ctx.ApplicationIdentity.Environment.GetHashCode(); var exception = action.Should().Throw <InvalidOperationException>().Which; Console.Out.WriteLine(exception); }); })); var result = await host.RunAsync(); result.State.Should().Be(VostokApplicationState.Exited); }
/// <summary> /// Checks whether given <paramref name="environment"/> satisfies all requirements imposed by <paramref name="application"/>. /// </summary> /// <returns><c>true</c> if all requirements are met, <c>false</c> otherwise (with at least one element in <paramref name="errors"/>).</returns> public static bool TryCheck( [NotNull] IVostokApplication application, [NotNull] IVostokHostingEnvironment environment, [NotNull] out List <string> errors) { if (application == null) { throw new ArgumentNullException(nameof(application)); } if (environment == null) { throw new ArgumentNullException(nameof(environment)); } errors = new List <string>(); CheckPort(application, environment, errors); CheckHostExtensions(application, environment, errors); CheckConfigurationTypes(application, environment, errors); return(errors.Count == 0); }
public async Task Should_allow_to_use_configuration_during_logging_setup(LogLevel logLevel) { application = new Application(); host = new VostokHost(new TestHostSettings(application, builder => { builder.SetupApplicationIdentity( id => id .SetProject("infra") .SetSubproject("vostok") .SetApplication("app") .SetInstance("1")); builder.SetupApplicationIdentity((id, ctx) => id.SetEnvironment("env")); builder.SetupLog((b, ctx) => { b.SetupConsoleLog( c => c.SetupMinimumLevelProvider( () => ctx.ConfigurationProvider.Get <ApplicationSettings>().LogLevel)); }); builder.SetupConfiguration( config => { config.AddSource(new ObjectSource(new { LogLevel = logLevel })); }); })); var result = await host.RunAsync(); result.State.Should().Be(VostokApplicationState.Exited); }
public static IEnumerable <RequiresHostExtension> GetRequiredHostExtensions([NotNull] IVostokApplication application) => RequirementAttributesHelper.GetAttributes <RequiresHostExtension>(application);
public static bool RequiresPort([NotNull] IVostokApplication application) => RequirementAttributesHelper.GetAttributes <RequiresPort>(application).Any();
public static void AddVostokEnvironment(this IServiceCollection services, IVostokHostingEnvironment environment, IVostokApplication application) { services .AddSingleton(environment) .AddSingleton(environment.ApplicationIdentity) .AddSingleton(environment.ApplicationLimits) .AddTransient(_ => environment.ApplicationReplicationInfo) .AddSingleton(environment.Metrics) .AddSingleton(environment.Log) .AddSingleton(environment.Tracer) .AddSingleton(environment.HerculesSink) .AddSingleton(environment.ConfigurationSource) .AddSingleton(environment.ConfigurationProvider) .AddSingleton(environment.ClusterConfigClient) .AddSingleton(environment.ServiceBeacon) .AddSingleton(environment.ServiceLocator) .AddSingleton(environment.ContextGlobals) .AddSingleton(environment.ContextProperties) .AddSingleton(environment.ContextConfiguration) .AddSingleton(environment.Datacenters) .AddSingleton(environment.HostExtensions); foreach (var(type, obj) in environment.HostExtensions.GetAll()) { services.AddSingleton(type, obj); } if (environment.HostExtensions.TryGet <IVostokApplicationDiagnostics>(out var diagnostics)) { services .AddSingleton(diagnostics.Info) .AddSingleton(diagnostics.HealthTracker); } AddSettingsProviders(services, RequirementDetector.GetRequiredConfigurations(application).Select(r => r.Type), environment.ConfigurationProvider); AddSettingsProviders(services, RequirementDetector.GetRequiredSecretConfigurations(application).Select(r => r.Type), environment.SecretConfigurationProvider); services.AddScoped(_ => FlowingContext.Globals.Get <IRequestInfo>()); }
public static IEnumerable <TRequirement> GetAttributes <TRequirement>(IVostokApplication application) where TRequirement : Attribute => GetApplicationTypes(application).SelectMany(GetAttributes <TRequirement>);
private static void CheckPort(IVostokApplication application, IVostokHostingEnvironment environment, List <string> errors) => CheckPortInternal(() => RequirementDetector.RequiresPort(application), environment, errors);
public TestHostSettings([NotNull] IVostokApplication application, [NotNull] VostokHostingEnvironmentSetup environmentSetup) : base(application, environmentSetup) { WarmupConfiguration = false; WarmupZooKeeper = false; }
private static void CheckHostExtensions(IVostokApplication application, IVostokHostingEnvironment environment, List <string> errors) => CheckHostExtensionsInternal(() => RequirementDetector.GetRequiredHostExtensions(application), environment, errors);
public VostokAspNetCoreApplicationBuilder(IVostokHostingEnvironment environment, IVostokApplication application, List <IDisposable> disposables) { this.environment = environment; hostFactory = new HostFactory(environment, application); hostFactory.SetupLogger(s => { s.IgnoredScopePrefixes = new[] { "Microsoft" }; }); kestrelBuilder = new VostokKestrelBuilder(); throttlingBuilder = new VostokThrottlingBuilder(environment, disposables); middlewaresBuilder = new VostokMiddlewaresBuilder(environment, disposables, throttlingBuilder); webHostBuilder = new VostokWebHostBuilder <TStartup>(environment, kestrelBuilder, middlewaresBuilder, disposables); }
public async Task Should_support_well_known_substitutions() { application = new Application( env => { Action assertion = () => { var settings = env.ConfigurationProvider.Get <ApplicationSettings>(); var secrets = env.SecretConfigurationProvider.Get <ApplicationSecretSettings>(); settings.A.Should().Be("infra"); settings.B.Should().Be("vostok"); settings.C.Should().Be("app"); settings.D.Should().Be("dev"); settings.E.Should().Be("1"); secrets.F.Should().Be("sd-app"); secrets.G.Should().Be("sd-env"); }; assertion.ShouldPassIn(10.Seconds(), 100.Milliseconds()); }); host = new VostokHost(new TestHostSettings(application, builder => { builder.SetupApplicationIdentity( id => id .SetProject("infra") .SetSubproject("vostok") .SetEnvironment("dev") .SetApplication("app") .SetInstance("1")); builder.SetupLog(log => log.SetupConsoleLog()); builder.SetBeaconApplication("sd-app"); builder.SetBeaconEnvironment("sd-env"); builder.SetupConfiguration( config => { config.AddSource(new ObjectSource(new { A = $"#{{{VostokConfigurationPlaceholders.IdentityProject}}}", B = $"#{{{VostokConfigurationPlaceholders.IdentitySubproject}}}", C = $"#{{{VostokConfigurationPlaceholders.IdentityApplication}}}", D = $"#{{{VostokConfigurationPlaceholders.IdentityEnvironment}}}", E = $"#{{{VostokConfigurationPlaceholders.IdentityInstance}}}" })); config.AddSecretSource(new ObjectSource(new { F = $"#{{{VostokConfigurationPlaceholders.ServiceDiscoveryApplication}}}", G = $"#{{{VostokConfigurationPlaceholders.ServiceDiscoveryEnvironment}}}", })); }); builder.SetupHerculesSink( (sink, context) => { context.ConfigurationProvider.Get <ApplicationSettings>(); context.SecretConfigurationProvider.Get <ApplicationSecretSettings>(); }); })); var result = await host.RunAsync(); result.State.Should().Be(VostokApplicationState.Exited); }
public VostokHostSettings([NotNull] IVostokApplication application, [NotNull] VostokHostingEnvironmentSetup environmentSetup) { Application = application ?? throw new ArgumentNullException(nameof(application)); EnvironmentSetup = environmentSetup ?? throw new ArgumentNullException(nameof(environmentSetup)); }
public static IEnumerable <RequiresMergedConfiguration> GetRequiredMergedConfigurations([NotNull] IVostokApplication application) => RequirementAttributesHelper.GetAttributes <RequiresMergedConfiguration>(application);
public ApplicationDisposable(IVostokApplication application, IVostokHostingEnvironment environment, ILog log) { this.application = application; this.environment = environment; this.log = log; }
/// <inheritdoc cref="IVostokApplication.InitializeAsync"/> public static void Initialize( [NotNull] this IVostokApplication application, [NotNull] IVostokHostingEnvironment environment) => application.InitializeAsync(environment).GetAwaiter().GetResult();