Skip to content

Commit

Permalink
upstream: fix panic on grpc unknown_service status on healthchecks (e…
Browse files Browse the repository at this point in the history
…nvoyproxy#10863)

Signed-off-by: Patrik Cyvoct <patrik@ptrk.io>
Signed-off-by: pengg <pengg@google.com>
  • Loading branch information
Sh4d1 authored and penguingao committed Apr 22, 2020
1 parent 4a02253 commit 06f4256
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Changes
* router: allow retries of streaming or incomplete requests. This removes stat `rq_retry_skipped_request_not_complete`.
* tracing: tracing configuration has been made fully dynamic and every HTTP connection manager
can now have a separate :ref:`tracing provider <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.Tracing.provider>`.
* upstream: fixed a bug where Envoy would panic when receiving a GRPC SERVICE_UNKNOWN status on the health check.

Deprecated
----------
Expand Down
6 changes: 4 additions & 2 deletions source/common/upstream/health_checker_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -793,9 +793,11 @@ void GrpcHealthCheckerImpl::GrpcActiveHealthCheckSession::logHealthCheckStatus(
case grpc::health::v1::HealthCheckResponse::UNKNOWN:
service_status = "unknown";
break;
case grpc::health::v1::HealthCheckResponse::SERVICE_UNKNOWN:
service_status = "service_unknown";
break;
default:
// Should not happen really, Protobuf should not parse undefined enums values.
NOT_REACHED_GCOVR_EXCL_LINE;
service_status = "unknown_healthcheck_response";
break;
}
}
Expand Down
28 changes: 28 additions & 0 deletions test/common/upstream/health_checker_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4452,6 +4452,34 @@ TEST_F(GrpcHealthCheckerImplTest, GrpcFailUnknown) {
cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health());
}

// Test SERVICE_UNKNOWN health status is considered unhealthy.
TEST_F(GrpcHealthCheckerImplTest, GrpcFailServiceUnknown) {
setupHC();
expectSingleHealthcheck(HealthTransition::Changed);
EXPECT_CALL(*event_logger_, logEjectUnhealthy(_, _, _));
EXPECT_CALL(*event_logger_, logUnhealthy(_, _, _, true));

respondServiceStatus(0, grpc::health::v1::HealthCheckResponse::SERVICE_UNKNOWN);
EXPECT_TRUE(cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthFlagGet(
Host::HealthFlag::FAILED_ACTIVE_HC));
EXPECT_EQ(Host::Health::Unhealthy,
cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health());
}

// Test non existent health status enum is considered unhealthy.
TEST_F(GrpcHealthCheckerImplTest, GrpcFailUnknownHealthStatus) {
setupHC();
expectSingleHealthcheck(HealthTransition::Changed);
EXPECT_CALL(*event_logger_, logEjectUnhealthy(_, _, _));
EXPECT_CALL(*event_logger_, logUnhealthy(_, _, _, true));

respondServiceStatus(0, static_cast<grpc::health::v1::HealthCheckResponse::ServingStatus>(999));
EXPECT_TRUE(cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthFlagGet(
Host::HealthFlag::FAILED_ACTIVE_HC));
EXPECT_EQ(Host::Health::Unhealthy,
cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->health());
}

// Test receiving GOAWAY is interpreted as connection close event.
TEST_F(GrpcHealthCheckerImplTest, GoAwayProbeInProgress) {
// FailureType::Network will be issued, it will render host unhealthy only if unhealthy_threshold
Expand Down

0 comments on commit 06f4256

Please sign in to comment.