diff --git a/src/api_manager/config_manager.cc b/src/api_manager/config_manager.cc index 874346886..9c557b059 100644 --- a/src/api_manager/config_manager.cc +++ b/src/api_manager/config_manager.cc @@ -36,7 +36,8 @@ ConfigManager::ConfigManager( std::function detect_rollout_func) : global_context_(global_context), rollout_apply_function_(rollout_apply_function), - fetch_throttle_window_in_s_(kFetchThrottleWindowInS) { + fetch_throttle_window_in_s_(kFetchThrottleWindowInS), + detect_rollout_func_(detect_rollout_func) { int detect_rollout_interval_s = kDetectRolloutChangeIntervalInS; if (global_context_->server_config() && global_context_->server_config()->has_service_management_config()) { @@ -59,9 +60,10 @@ ConfigManager::ConfigManager( service_management_fetch_.reset(new ServiceManagementFetch(global_context)); - if (detect_rollout_func) { + if (detect_rollout_func_) { detect_rollout_change_timer_ = global_context_->env()->StartPeriodicTimer( - std::chrono::seconds(detect_rollout_interval_s), detect_rollout_func); + std::chrono::seconds(detect_rollout_interval_s), + [this]() { OnDetectRolloutChangeTimer(); }); } } @@ -94,6 +96,20 @@ void ConfigManager::SetLatestRolloutId( [this]() { OnRolloutsRefreshTimer(); }); } +void ConfigManager::OnDetectRolloutChangeTimer() { + global_context_->env()->LogDebug("Detect rollout change timer starts"); + std::string audience; + GlobalFetchServiceAccountToken( + global_context_, audience, [this](utils::Status status) { + if (!status.ok()) { + global_context_->env()->LogError( + "Fetch access token unexpected status: " + status.ToString()); + return; + } + detect_rollout_func_(); + }); +} + void ConfigManager::OnRolloutsRefreshTimer() { global_context_->env()->LogInfo("Fetch timer starts"); fetch_timer_->Stop(); diff --git a/src/api_manager/config_manager.h b/src/api_manager/config_manager.h index 8c12a46c4..e0cd0ea31 100644 --- a/src/api_manager/config_manager.h +++ b/src/api_manager/config_manager.h @@ -97,7 +97,9 @@ class ConfigManager { // Fetch ServiceConfig details from the latest successful rollouts // https://goo.gl/I2nD4M void FetchConfigs(std::shared_ptr config_fetch_info); - // Period timer task + // Periodical timer to detect rollout changes + void OnDetectRolloutChangeTimer(); + // One time timer to throttle service fetching time. void OnRolloutsRefreshTimer(); // Rollout response handler void OnRolloutResponse(const utils::Status& status, std::string&& rollouts); @@ -124,6 +126,8 @@ class ConfigManager { std::default_random_engine random_generator_; std::unique_ptr> random_dist_; + // the callback function to detect rollout change. + std::function detect_rollout_func_; // Periodic timer to send empty report to detect latest rollout change. std::unique_ptr detect_rollout_change_timer_; }; diff --git a/src/nginx/t/config_rollouts_by_timer.t b/src/nginx/t/config_rollouts_by_timer.t index 32b0771bc..32ed09da2 100644 --- a/src/nginx/t/config_rollouts_by_timer.t +++ b/src/nginx/t/config_rollouts_by_timer.t @@ -45,8 +45,9 @@ my $NginxPort = ApiManager::pick_port(); my $BackendPort = ApiManager::pick_port(); my $ServiceControlPort = ApiManager::pick_port(); my $ServiceManagementPort = ApiManager::pick_port(); +my $MetadataPort = ApiManager::pick_port(); -my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(7); +my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(9); # Save service configuration that disables the report cache. # Report request will be sent for each client request @@ -109,6 +110,9 @@ events { http { %%TEST_GLOBALS_HTTP%% server_tokens off; + endpoints { + metadata_server http://127.0.0.1:${MetadataPort}; + } server { listen 127.0.0.1:${NginxPort}; server_name localhost; @@ -135,11 +139,14 @@ $t->run_daemon( \&servicecontrol, $t, $ServiceControlPort, 'servicecontrol.log', $report_done); $t->run_daemon( \&servicemanagement, $t, $ServiceManagementPort, 'servicemanagement.log', $rollout_done); +$t->run_daemon(\&metadata, $t, $MetadataPort, 'metadata.log'); is( $t->waitforsocket("127.0.0.1:${ServiceControlPort}"), 1, 'Service control socket ready.' ); is( $t->waitforsocket("127.0.0.1:${ServiceManagementPort}"), 1, 'Service management socket ready.' ); +is($t->waitforsocket("127.0.0.1:${MetadataPort}"), 1, 'Metadata socket ready.'); + $t->run(); ################################################################################ @@ -177,6 +184,12 @@ is($endpoints_status->{processes}[0]->{espStatus}[0]->{serviceConfigRollouts}-> $t->stop_daemons(); +# Check service control requests... +my @servicecontrol_requests = ApiManager::read_http_stream($t, 'servicecontrol.log'); +my $request = shift @servicecontrol_requests; +is($request->{headers}->{authorization}, + 'Bearer ya29.7gFRTEGmovWacYDnQIpC9X9Qp8cH0sgQyWVrZaB1Eg1WoAhQMSG4L2rtaHk1', + 'empty report was authenticated'); ################################################################################ @@ -262,4 +275,25 @@ EOF $server->run(); } +sub metadata { + my ($t, $port, $file) = @_; + my $server = HttpServer->new($port, $t->testdir() . '/' . $file) + or die "Can't create test server socket: $!\n"; + local $SIG{PIPE} = 'IGNORE'; + + $server->on('GET', '/computeMetadata/v1/instance/service-accounts/default/token', <<'EOF'); +HTTP/1.1 200 OK +Metadata-Flavor: Google +Content-Type: application/json + +{ + "access_token":"ya29.7gFRTEGmovWacYDnQIpC9X9Qp8cH0sgQyWVrZaB1Eg1WoAhQMSG4L2rtaHk1", + "expires_in":200, + "token_type":"Bearer" +} +EOF + + $server->run(); +} + ################################################################################