예제 #1
0
        public async Task Run([EventGridTrigger] EventGridEvent eventGridEvent)
        {
            var sentinel = _configuration["appsection:sentinel"];

            // Invalidate cached key-values before calling TryRefreshAsync
            _configurationRefresher.SetDirty(TimeSpan.FromSeconds(0));
            await _configurationRefresher.TryRefreshAsync();

            while (sentinel == _configuration["appsection:sentinel"])
            {
                Console.WriteLine(
                    $"Sentinel value is not updated yet: {_configuration["appsection:sentinel"]}");
                await Task.Delay(TimeSpan.FromSeconds(1));

                await _configurationRefresher.TryRefreshAsync();
            }
            var message = new Dictionary <string, string>
            {
                { "appsection:key1", _configuration["appsection:key1"] },
                { "appsection:key2", _configuration.GetValue <string>("appsection:key2") },
                { "appsection:sentinel", _configuration["appsection:sentinel"] }
            };

            Console.WriteLine(JsonConvert.SerializeObject(message));
        }
예제 #2
0
        public void RefreshTests_TryRefreshAsyncReturnsFalseForAuthenticationFailedException()
        {
            IConfigurationRefresher refresher = null;
            var mockResponse = new Mock <Response>();
            var mockClient   = new Mock <ConfigurationClient>(MockBehavior.Strict, TestHelpers.CreateMockEndpointString());

            mockClient.SetupSequence(c => c.GetConfigurationSettingsAsync(It.IsAny <SettingSelector>(), It.IsAny <CancellationToken>()))
            .Returns(new MockAsyncPageable(_kvCollection));

            var innerException = new AuthenticationFailedException("Authentication failed.")
            {
                Source = "Azure.Identity"
            };

            mockClient.SetupSequence(c => c.GetConfigurationSettingAsync("TestKey1", It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(Response.FromValue(_kvCollection.FirstOrDefault(s => s.Key == "TestKey1"), mockResponse.Object)))
            .Returns(Task.FromResult(Response.FromValue(_kvCollection.FirstOrDefault(s => s.Key == "TestKey1"), mockResponse.Object)))
            .Throws(new KeyVaultReferenceException(innerException.Message, innerException));

            var config = new ConfigurationBuilder()
                         .AddAzureAppConfiguration(options =>
            {
                options.Client = mockClient.Object;
                options.Select("TestKey*");
                options.ConfigureRefresh(refreshOptions =>
                {
                    refreshOptions.Register("TestKey1")
                    .SetCacheExpiration(TimeSpan.FromSeconds(1));
                });

                refresher = options.GetRefresher();
            })
                         .Build();

            Assert.Equal("TestValue1", config["TestKey1"]);
            FirstKeyValue.Value = "newValue";

            // Wait for the cache to expire
            Thread.Sleep(1500);

            // Second call to GetConfigurationSettingAsync does not throw
            Assert.True(refresher.TryRefreshAsync().Result);

            // Wait for the cache to expire
            Thread.Sleep(1500);

            // Third call to GetConfigurationSettingAsync throws KeyVaultReferenceException
            Assert.False(refresher.TryRefreshAsync().Result);
        }
        private static async Task Run(CancellationToken token)
        {
            string        display = string.Empty;
            StringBuilder sb      = new StringBuilder();

            while (!token.IsCancellationRequested)
            {
                // Trigger an async refresh for registered configuration settings without wait
                _ = _refresher.TryRefreshAsync();

                sb.AppendLine($"{Configuration["AppName"]} has been configured to run in {Configuration["Language"]}");
                sb.AppendLine();

                sb.AppendLine(string.Equals(Configuration["Language"], "spanish", StringComparison.OrdinalIgnoreCase) ? "Buenos Dias." : "Good morning");
                sb.AppendLine();

                sb.AppendLine("Press any key to exit...");
                await Task.Delay(1000);

                if (!sb.ToString().Equals(display))
                {
                    display = sb.ToString();

                    Console.Clear();
                    Console.Write(display);
                }

                sb.Clear();
            }
        }
예제 #4
0
        public void RefreshTests_TryRefreshAsyncReturnsFalseOnRequestFailedException()
        {
            IConfigurationRefresher refresher = null;
            var mockClient = GetMockConfigurationClient();

            var config = new ConfigurationBuilder()
                         .AddAzureAppConfiguration(options =>
            {
                options.Client = mockClient.Object;
                options.Select("TestKey*");
                options.ConfigureRefresh(refreshOptions =>
                {
                    refreshOptions.Register("TestKey1")
                    .SetCacheExpiration(TimeSpan.FromSeconds(1));
                });

                refresher = options.GetRefresher();
            })
                         .Build();

            Assert.Equal("TestValue1", config["TestKey1"]);
            FirstKeyValue.Value = "newValue";

            mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .Throws(new RequestFailedException("Request failed."));

            // Wait for the cache to expire
            Thread.Sleep(1500);

            bool result = refresher.TryRefreshAsync().Result;

            Assert.False(result);

            Assert.NotEqual("newValue", config["TestKey1"]);
        }
예제 #5
0
        public void RefreshTests_TryRefreshAsyncUpdatesConfigurationAndReturnsTrueOnSuccess()
        {
            IConfigurationRefresher refresher = null;
            var mockClient = GetMockConfigurationClient();

            var config = new ConfigurationBuilder()
                         .AddAzureAppConfiguration(options =>
            {
                options.Client = mockClient.Object;
                options.Select("TestKey*");
                options.ConfigureRefresh(refreshOptions =>
                {
                    refreshOptions.Register("TestKey1")
                    .SetCacheExpiration(TimeSpan.FromSeconds(1));
                });

                refresher = options.GetRefresher();
            })
                         .Build();

            Assert.Equal("TestValue1", config["TestKey1"]);
            FirstKeyValue.Value = "newValue";

            // Wait for the cache to expire
            Thread.Sleep(1500);

            bool result = refresher.TryRefreshAsync().Result;

            Assert.True(result);

            Assert.Equal("newValue", config["TestKey1"]);
        }
예제 #6
0
        public async Task OnGet()
        {
            _configurationRefresher.SetDirty(TimeSpan.FromSeconds(1));
            await Task.Delay(1000);

            bool success = await _configurationRefresher.TryRefreshAsync();
        }
예제 #7
0
        public async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
        {
            log.LogInformation("El trigger HTTP con C#, proceso un request.");
            string keyVaultEntry   = "proxymusk";
            string messageKeyVault = "keyvault es local";
            await _configurationRefresher.TryRefreshAsync();

            if (!isLocal)
            {
                await _configurationRefresher.RefreshAsync();

                messageKeyVault = _configuration[keyVaultEntry];
            }

            bool flag = await _featureManagerSnapshot.IsEnabledAsync("ActivacionMensaje");

            string keyName = "TestApp:Settings:Message02";
            string message = _configuration[keyName];

            if (flag)
            {
                GuardaenBD(message, log);
            }
            return(message != null
                ? (ActionResult) new OkObjectResult($"La cadena recuperada desde AppConfig fue '{message}', y el valor desde KeyVault era '{messageKeyVault}' {flag} :)")
                : new BadRequestObjectResult($"Please create a key-value with the key '{keyName}' in App Configuration, gracias."));
        }
예제 #8
0
        public async Task Run([TimerTrigger("0 */1 * * * *")] TimerInfo myTimer, ILogger log)
        {
            log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

            await _configurationRefresher.TryRefreshAsync();

            log.LogInformation($"Version {_configuration.GetValue<string>("AzureFunction:Settings:Version")}");
            log.LogInformation($"Blob Connection String {_configuration.GetValue<string>("AzureFunction:Settings:BlobConnectionString")}");
            log.LogInformation($"B2C Tenant {_configuration.GetValue<string>("AzureFunction:Settings:B2CTenant")}");
        }
예제 #9
0
        public async Task <IActionResult> ScheduleJob(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "schedule")] HttpRequest req,
            ILogger log)
        {
            await _configurationRefresher.TryRefreshAsync();

            if (await _featureManagerSnapshot.IsEnabledAsync("RunLoadTests"))
            {
                string job = await new StreamReader(req.Body).ReadToEndAsync();
                await _client.SendMessageAsync(job);
            }
            return((IActionResult) new OkResult());
        }
예제 #10
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            await _configurationRefresher.TryRefreshAsync();

            string keyName = "TestApp:Settings:Message";
            string message = _configuration[keyName];

            return(message != null
                ? (ActionResult) new OkObjectResult(message)
                : new BadRequestObjectResult($"Please create a key-value with the key '{keyName}' in App Configuration."));
        }
예제 #11
0
        public async Task <string> CheckOtherShipsFlag([ActivityTrigger] object obj)
        {
            await _refresher.TryRefreshAsync();

            var shipFlag      = "The West India Company";
            var usePirateShip = await this._featureManager.IsEnabledAsync("pirate-flag");

            if (usePirateShip)
            {
                shipFlag = "Pirate";
            }

            return(shipFlag);
        }
예제 #12
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            await _configurationRefresher.TryRefreshAsync();

            string message = await _featureManager.IsEnabledAsync("Beta")
                ? "The Feature Flag 'Beta' is turned ON"
                : "The Feature Flag 'Beta' is turned OFF";

            return((ActionResult) new OkObjectResult(message));
        }
예제 #13
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
            ExecutionContext context,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            await _configurationRefresher.TryRefreshAsync();

            string loaderIOVerificationToken = _configuration["EnterpriseServerless:LoaderIO_VerificationToken"];
            string responseMessage           = string.IsNullOrEmpty(loaderIOVerificationToken)
                ? "This HTTP triggered function executed successfully, however its missing the verification token."
                : loaderIOVerificationToken;

            return(new OkObjectResult(responseMessage));
        }
예제 #14
0
        public async Task <IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            await _refresher.TryRefreshAsync();

            var shipFlag      = "The India Company";
            var usePirateShip = await this._featureManager.IsEnabledAsync("pirate-flag");

            if (usePirateShip)
            {
                shipFlag = "Pirate";
            }

            return((ActionResult) new OkObjectResult($"The ship has a {shipFlag} flag "));
        }
        public void OverwriteLoggerFactory()
        {
            IConfigurationRefresher refresher = null;
            var mockClient = GetMockConfigurationClient();

            mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny <ConfigurationSetting>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()))
            .Throws(new RequestFailedException(403, "Forbidden"));

            var mockLogger1        = new Mock <ILogger>();
            var mockLoggerFactory1 = new Mock <ILoggerFactory>();

            mockLoggerFactory1.Setup(mlf => mlf.CreateLogger(LoggingConstants.AppConfigRefreshLogCategory)).Returns(mockLogger1.Object);

            var mockLogger2        = new Mock <ILogger>();
            var mockLoggerFactory2 = new Mock <ILoggerFactory>();

            mockLoggerFactory2.Setup(mlf => mlf.CreateLogger(LoggingConstants.AppConfigRefreshLogCategory)).Returns(mockLogger2.Object);

            var config = new ConfigurationBuilder()
                         .AddAzureAppConfiguration(options =>
            {
                options.Client = mockClient.Object;
                options.ConfigureRefresh(refreshOptions =>
                {
                    refreshOptions.Register("TestKey1", "label")
                    .SetCacheExpiration(CacheExpirationTime);
                });

                refresher = options.GetRefresher();
            })
                         .Build();

            Assert.Equal("TestValue1", config["TestKey1"]);
            FirstKeyValue.Value = "newValue1";

            // Set LoggerFactory
            refresher.LoggerFactory = mockLoggerFactory1.Object;

            // Overwrite LoggerFactory
            refresher.LoggerFactory = mockLoggerFactory2.Object;

            Thread.Sleep(CacheExpirationTime);
            refresher.TryRefreshAsync().Wait();

            Assert.NotEqual("newValue1", config["TestKey1"]);
            Assert.True(ValidateLoggedError(mockLogger2, LoggingConstants.RefreshFailedDueToAuthenticationError));
        }
예제 #16
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            // Signal to refresh the configuration if the registered key(s) is modified.
            // This will be a no-op if the cache expiration time window is not reached.
            // The configuration is refreshed asynchronously without blocking the execution of the current function.
            _ = _configurationRefresher.TryRefreshAsync();

            string message = _settings.Message;

            return(message != null
                ? (ActionResult) new OkObjectResult(message)
                : new BadRequestObjectResult($"Please create a key-value with the key 'TestApp:Settings:Message' in Azure App Configuration."));
        }
예제 #17
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            // Signal to refresh the feature flags from Azure App Configuration.
            // This will be a no-op if the cache expiration time window is not reached.
            // Remove the 'await' operator if it's preferred to refresh without blocking.
            await _configurationRefresher.TryRefreshAsync();

            string featureName    = "Beta";
            bool   featureEnalbed = await _featureManagerSnapshot.IsEnabledAsync(featureName);

            return(featureEnalbed
                ? (ActionResult) new OkObjectResult($"{featureName} feature is On")
                : new BadRequestObjectResult($"{featureName} feature is Off (or the feature flag '{featureName}' is not present in Azure App Configuration)."));
        }
        public void ValidateOperationCanceledExceptionLoggedDuringRefresh()
        {
            IConfigurationRefresher refresher = null;
            var mockClient = GetMockConfigurationClient();

            var mockLogger        = new Mock <ILogger>();
            var mockLoggerFactory = new Mock <ILoggerFactory>();

            mockLoggerFactory.Setup(mlf => mlf.CreateLogger(LoggingConstants.AppConfigRefreshLogCategory)).Returns(mockLogger.Object);

            var config = new ConfigurationBuilder()
                         .AddAzureAppConfiguration(options =>
            {
                options.Client = mockClient.Object;
                options.ConfigureRefresh(refreshOptions =>
                {
                    refreshOptions.Register("TestKey1", "label")
                    .SetCacheExpiration(CacheExpirationTime);
                });

                refresher = options.GetRefresher();
            })
                         .Build();

            Assert.Equal("TestValue1", config["TestKey1"]);
            FirstKeyValue.Value = "newValue1";

            Thread.Sleep(CacheExpirationTime);
            refresher.LoggerFactory = mockLoggerFactory.Object;

            using var cancellationSource = new CancellationTokenSource();
            cancellationSource.CancelAfter(TimeSpan.Zero);
            refresher.TryRefreshAsync(cancellationSource.Token).Wait();

            Assert.NotEqual("newValue1", config["TestKey1"]);
            Assert.True(ValidateLoggedError(mockLogger, LoggingConstants.RefreshCanceledError));
        }
        public void ValidateKeyVaultExceptionLoggedDuringRefresh()
        {
            IConfigurationRefresher refresher = null;
            TimeSpan cacheExpirationTime      = TimeSpan.FromSeconds(1);

            // Mock ConfigurationClient
            var mockResponse = new Mock <Response>();
            var mockClient   = new Mock <ConfigurationClient>(MockBehavior.Strict, TestHelpers.CreateMockEndpointString());

            Response <ConfigurationSetting> GetTestKey(string key, string label, CancellationToken cancellationToken)
            {
                return(Response.FromValue(TestHelpers.CloneSetting(sentinelKv), mockResponse.Object));
            }

            Response <ConfigurationSetting> GetIfChanged(ConfigurationSetting setting, bool onlyIfChanged, CancellationToken cancellationToken)
            {
                var unchanged = sentinelKv.Key == setting.Key && sentinelKv.Label == setting.Label && sentinelKv.Value == setting.Value;
                var response  = new MockResponse(unchanged ? 304 : 200);

                return(Response.FromValue(sentinelKv, response));
            }

            // No KVR during startup; return KVR during refresh operation to see error because ConfigureKeyVault is missing
            mockClient.SetupSequence(c => c.GetConfigurationSettingsAsync(It.IsAny <SettingSelector>(), It.IsAny <CancellationToken>()))
            .Returns(new MockAsyncPageable(_kvCollection.Select(setting => TestHelpers.CloneSetting(setting)).ToList()))
            .Returns(new MockAsyncPageable(new List <ConfigurationSetting> {
                _kvr
            }));
            mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((Func <string, string, CancellationToken, Response <ConfigurationSetting> >)GetTestKey);
            mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny <ConfigurationSetting>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((Func <ConfigurationSetting, bool, CancellationToken, Response <ConfigurationSetting> >)GetIfChanged);

            // Mock ILogger and ILoggerFactory
            var mockLogger        = new Mock <ILogger>();
            var mockLoggerFactory = new Mock <ILoggerFactory>();

            mockLoggerFactory.Setup(mlf => mlf.CreateLogger(LoggingConstants.AppConfigRefreshLogCategory)).Returns(mockLogger.Object);

            var config = new ConfigurationBuilder()
                         .AddAzureAppConfiguration(options =>
            {
                options.Client = mockClient.Object;
                options.ConfigureRefresh(refreshOptions =>
                {
                    refreshOptions.Register("SentinelKey", refreshAll: true)
                    .SetCacheExpiration(CacheExpirationTime);
                });
                refresher = options.GetRefresher();
            })
                         .Build();

            Assert.Equal("SentinelValue", config["SentinelKey"]);

            // Update sentinel key-value to trigger refreshAll operation
            sentinelKv.Value = "UpdatedSentinelValue";
            Thread.Sleep(CacheExpirationTime);
            refresher.LoggerFactory = mockLoggerFactory.Object;
            refresher.TryRefreshAsync().Wait();

            Assert.True(ValidateLoggedError(mockLogger, LoggingConstants.RefreshFailedDueToKeyVaultError));
        }
예제 #20
0
        public void RefreshTests_SentinelKeyNotUpdatedOnRefreshAllFailure()
        {
            var serviceCollection = new List <ConfigurationSetting>(_kvCollection);
            var mockResponse      = new Mock <Response>();
            var mockClient        = new Mock <ConfigurationClient>(MockBehavior.Strict, TestHelpers.CreateMockEndpointString());

            Response <ConfigurationSetting> GetIfChanged(ConfigurationSetting setting, bool onlyIfChanged, CancellationToken cancellationToken)
            {
                var newSetting = serviceCollection.FirstOrDefault(s => s.Key == setting.Key);
                var unchanged  = (newSetting.Key == setting.Key && newSetting.Label == setting.Label && newSetting.Value == setting.Value);
                var response   = new MockResponse(unchanged ? 304 : 200);

                return(Response.FromValue(newSetting, response));
            }

            mockClient.SetupSequence(c => c.GetConfigurationSettingsAsync(It.IsAny <SettingSelector>(), It.IsAny <CancellationToken>()))
            .Returns(new MockAsyncPageable(serviceCollection.Select(setting => TestHelpers.CloneSetting(setting)).ToList()))
            .Throws(new RequestFailedException(429, "Too many requests"))
            .Returns(new MockAsyncPageable(serviceCollection.Select(setting =>
            {
                setting.Value = "newValue";
                return(TestHelpers.CloneSetting(setting));
            }).ToList()));

            mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny <ConfigurationSetting>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((Func <ConfigurationSetting, bool, CancellationToken, Response <ConfigurationSetting> >)GetIfChanged);

            IConfigurationRefresher refresher = null;

            var config = new ConfigurationBuilder()
                         .AddAzureAppConfiguration(options =>
            {
                options.Client = mockClient.Object;
                options.Select("TestKey*", "label");
                options.ConfigureRefresh(refreshOptions =>
                {
                    refreshOptions.Register("TestKey1", "label", refreshAll: true)
                    .SetCacheExpiration(TimeSpan.FromSeconds(1));
                });

                refresher = options.GetRefresher();
            })
                         .Build();

            Assert.Equal("TestValue1", config["TestKey1"]);
            Assert.Equal("TestValue2", config["TestKey2"]);
            Assert.Equal("TestValue3", config["TestKey3"]);

            serviceCollection.ForEach(kv => kv.Value = "newValue");

            // Wait for the cache to expire
            Thread.Sleep(1500);

            bool firstRefreshResult = refresher.TryRefreshAsync().Result;

            Assert.False(firstRefreshResult);

            Assert.Equal("TestValue1", config["TestKey1"]);
            Assert.Equal("TestValue2", config["TestKey2"]);
            Assert.Equal("TestValue3", config["TestKey3"]);

            // Wait for the cache to expire
            Thread.Sleep(1500);

            bool secondRefreshResult = refresher.TryRefreshAsync().Result;

            Assert.True(secondRefreshResult);

            Assert.Equal("newValue", config["TestKey1"]);
            Assert.Equal("newValue", config["TestKey2"]);
            Assert.Equal("newValue", config["TestKey3"]);
        }
 public ApplicationConfigService(IConfiguration configuration, IConfigurationRefresherProvider refresherProvider)
 {
     _config          = configuration;
     _configRefresher = refresherProvider.Refreshers.First();
     _configRefresher.TryRefreshAsync();
 }